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
{\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.

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).
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},

View File

@@ -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;

View File

@@ -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"));
}

View File

@@ -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
// ----------------------------------------------------------------------------