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:
Mattia Barbon
2003-09-01 20:20:21 +00:00
parent 78d774068b
commit e21011866e
5 changed files with 221 additions and 24 deletions

View File

@@ -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 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 {\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 arbitrary characters. The ASCII NUL character is allowed, but be aware that
taken when passing strings containing it to other functions. 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 wxString works with both ASCII (traditional, 7 or 8 bit, characters) as well as
Unicode (wide characters) strings. Unicode (wide characters) strings.

View File

@@ -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). are not supported, nor all methods which use them).
These standard functions are not documented in this manual so please see the STL documentation. 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 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 You may notice that wxString sometimes has many functions which do the same
thing like, for example, \helpref{Length()}{wxstringlength}, thing like, for example, \helpref{Length()}{wxstringlength},

View File

@@ -523,6 +523,7 @@ public:
{ return find_first_of(str.c_str(), nStart); } { return find_first_of(str.c_str(), nStart); }
// same as above // 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 = 0) const;
size_t find_first_of(const wxChar* sz, size_t nStart, size_t n) const;
// same as find(char, size_t) // same as find(char, size_t)
size_t find_first_of(wxChar c, size_t nStart = 0) const size_t find_first_of(wxChar c, size_t nStart = 0) const
{ return find(c, nStart); } { return find(c, nStart); }
@@ -531,6 +532,7 @@ public:
{ return find_last_of(str.c_str(), nStart); } { return find_last_of(str.c_str(), nStart); }
// same as above // 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 = npos) const;
size_t find_last_of(const wxChar* sz, size_t nStart, size_t n) const;
// same as above // same as above
size_t find_last_of(wxChar c, size_t nStart = npos) const size_t find_last_of(wxChar c, size_t nStart = npos) const
{ return rfind(c, nStart); } { return rfind(c, nStart); }
@@ -542,13 +544,15 @@ public:
{ return find_first_not_of(str.c_str(), nStart); } { return find_first_not_of(str.c_str(), nStart); }
// same as above // 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 = 0) const;
size_t find_first_not_of(const wxChar* sz, size_t nStart, size_t n) const;
// same as above // same as above
size_t find_first_not_of(wxChar ch, size_t nStart = 0) const; size_t find_first_not_of(wxChar ch, size_t nStart = 0) const;
// as strcspn() // as strcspn()
size_t find_last_not_of(const wxStringBase& str, size_t nStart = npos) const 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 // 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 = npos) const;
size_t find_last_not_of(const wxChar* sz, size_t nStart, size_t n) const;
// same as above // same as above
size_t find_last_not_of(wxChar ch, size_t nStart = npos) const; size_t find_last_not_of(wxChar ch, size_t nStart = npos) const;

View File

@@ -97,7 +97,7 @@
#undef TEST_ALL #undef TEST_ALL
static const bool TEST_ALL = true; static const bool TEST_ALL = true;
#else #else
#define TEST_HASHSET #define TEST_STRINGS
static const bool TEST_ALL = false; static const bool TEST_ALL = false;
#endif #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, void is(int line, const wxChar& got, const wxChar& expected,
const wxString& msg = wxEmptyString) const wxString& msg = wxEmptyString)
{ {
@@ -6558,11 +6572,26 @@ void is(int line, const wxChar& got, const wxChar& expected,
ok(line, isOk, msg); ok(line, isOk, msg);
if( !isOk ) if( !isOk )
{ {
wxPuts("Got: " + got); wxPuts(_T("Got: ") + got);
wxPuts("Expected: " + expected); 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() void TestStdString()
{ {
wxPuts(_T("*** Testing std::string operations ***\n")); wxPuts(_T("*** Testing std::string operations ***\n"));
@@ -6652,6 +6681,77 @@ void TestStdString()
is( __LINE__, *it2, _T('g') ); is( __LINE__, *it2, _T('g') );
ok( __LINE__, it3 == s7.end() ); 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 // test insert
s1 = s2 = s3 = s4 = s5 = s6 = s7 = s8 = _T("aaaa"); s1 = s2 = s3 = s4 = s5 = s6 = s7 = s8 = _T("aaaa");
s9 = s10 = _T("cdefg"); s9 = s10 = _T("cdefg");
@@ -6702,6 +6802,49 @@ void TestStdString()
is( __LINE__, s6, s9); is( __LINE__, s6, s9);
is( __LINE__, s7, _T("QWwertyP") ); 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")); wxPuts(_T("*** Testing std::string operations finished ***\n"));
} }

View File

@@ -482,12 +482,30 @@ size_t wxStringBase::rfind(const wxStringBase& str, size_t nStart) const
wxASSERT( str.GetStringData()->IsValid() ); wxASSERT( str.GetStringData()->IsValid() );
wxASSERT( nStart == npos || nStart <= length() ); wxASSERT( nStart == npos || nStart <= length() );
// TODO could be made much quicker than that if ( length() >= str.length() )
const wxChar *p = c_str() + (nStart == npos ? length() : nStart); {
while ( p >= c_str() + str.length() ) { // avoids a corner case later
if ( wxStrncmp(p - str.length(), str.c_str(), str.length()) == 0 ) if ( length() == 0 && str.length() == 0 )
return p - str.length() - c_str(); return 0;
p--;
// "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; return npos;
@@ -530,11 +548,17 @@ size_t wxStringBase::find_first_of(const wxChar* sz, size_t nStart) const
return npos; 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 size_t wxStringBase::find_last_of(const wxChar* sz, size_t nStart) const
{ {
if ( nStart == npos ) if ( nStart == npos )
{ {
nStart = length(); nStart = length() - 1;
} }
else 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()") ); _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) ) if ( wxStrchr(sz, *p) )
return p - c_str(); return p - c_str();
@@ -551,6 +575,12 @@ size_t wxStringBase::find_last_of(const wxChar* sz, size_t nStart) const
return npos; 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 size_t wxStringBase::find_first_not_of(const wxChar* sz, size_t nStart) const
{ {
if ( nStart == npos ) 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 ) if ( nAccept >= length() - nStart )
return npos; return npos;
else 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 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 ) if ( nStart == npos )
{ {
nStart = length(); nStart = length() - 1;
} }
else else
{ {
wxASSERT( nStart <= length() ); 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) ) if ( !wxStrchr(sz, *p) )
return p - c_str(); return p - c_str();
@@ -602,18 +638,24 @@ size_t wxStringBase::find_last_not_of(const wxChar* sz, size_t nStart) const
return npos; 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 size_t wxStringBase::find_last_not_of(wxChar ch, size_t nStart) const
{ {
if ( nStart == npos ) if ( nStart == npos )
{ {
nStart = length(); nStart = length() - 1;
} }
else else
{ {
wxASSERT( nStart <= length() ); 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 ) if ( *p != ch )
return p - c_str(); return p - c_str();
@@ -2172,6 +2214,13 @@ void wxArrayString::Remove(const wxChar *sz)
RemoveAt(iIndex); RemoveAt(iIndex);
} }
void wxArrayString::assign(const_iterator first, const_iterator last)
{
reserve(last - first);
for(; first != last; ++first)
push_back(*first);
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// sorting // sorting
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------