+ wxASSERT( str.GetStringData()->IsValid() );
+ wxASSERT( nStart == npos || nStart <= length() );
+
+ 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();
+ }
+ } while ( cursor-- > c_str() );
+ }
+
+ return npos;
+}
+
+size_t wxStringBase::rfind(const wxChar* sz, size_t nStart, size_t n) const
+{
+ return rfind(wxStringBase(sz, n), nStart);
+}
+
+size_t wxStringBase::rfind(wxChar ch, size_t nStart) const
+{
+ if ( nStart == npos )
+ {
+ nStart = length();
+ }
+ else
+ {
+ wxASSERT( nStart <= length() );
+ }
+
+ const wxChar *actual;
+ for ( actual = c_str() + ( nStart == npos ? length() : nStart + 1 );
+ actual > c_str(); --actual )
+ {
+ if ( *(actual - 1) == ch )
+ return (actual - 1) - c_str();
+ }
+
+ return npos;
+}
+
+size_t wxStringBase::find_first_of(const wxChar* sz, size_t nStart) const
+{
+ const wxChar *start = c_str() + nStart;
+ const wxChar *firstOf = wxStrpbrk(start, sz);
+ if ( firstOf )
+ return firstOf - c_str();
+ else
+ 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() - 1;
+ }
+ else
+ {
+ wxASSERT_MSG( nStart <= length(),
+ _T("invalid index in find_last_of()") );
+ }
+
+ for ( const wxChar *p = c_str() + nStart; p >= c_str(); --p )
+ {
+ if ( wxStrchr(sz, *p) )
+ return p - c_str();
+ }
+
+ 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 )
+ {
+ nStart = length();
+ }
+ else
+ {
+ wxASSERT( nStart <= length() );
+ }
+
+ size_t nAccept = wxStrspn(c_str() + nStart, sz);
+ if ( nAccept >= length() - nStart )
+ return npos;
+ else
+ 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
+{
+ wxASSERT( nStart <= length() );
+
+ for ( const wxChar *p = c_str() + nStart; *p; p++ )
+ {
+ if ( *p != ch )
+ return p - c_str();
+ }
+
+ return npos;
+}
+
+size_t wxStringBase::find_last_not_of(const wxChar* sz, size_t nStart) const
+{
+ if ( nStart == npos )
+ {
+ nStart = length() - 1;
+ }
+ else
+ {
+ wxASSERT( nStart <= length() );
+ }
+
+ for ( const wxChar *p = c_str() + nStart; p >= c_str(); --p )
+ {
+ if ( !wxStrchr(sz, *p) )
+ return p - c_str();
+ }
+
+ 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() - 1;
+ }
+ else
+ {
+ wxASSERT( nStart <= length() );
+ }
+
+ for ( const wxChar *p = c_str() + nStart; p >= c_str(); --p )
+ {
+ if ( *p != ch )
+ return p - c_str();
+ }
+
+ return npos;
+}
+
+wxStringBase& wxStringBase::replace(size_t nStart, size_t nLen,
+ const wxChar *sz)
+{
+ wxASSERT_MSG( nStart <= length(),
+ _T("index out of bounds in wxStringBase::replace") );
+ size_t strLen = length() - nStart;
+ nLen = strLen < nLen ? strLen : nLen;
+
+ wxStringBase strTmp;
+ strTmp.reserve(length()); // micro optimisation to avoid multiple mem allocs
+
+ if ( nStart != 0 )
+ strTmp.append(c_str(), nStart);
+ strTmp.append(sz);
+ strTmp.append(c_str() + nStart + nLen);
+
+ swap(strTmp);
+ return *this;
+}
+
+wxStringBase& wxStringBase::replace(size_t nStart, size_t nLen,
+ size_t nCount, wxChar ch)
+{
+ return replace(nStart, nLen, wxStringBase(ch, nCount).c_str());
+}
+
+wxStringBase& wxStringBase::replace(size_t nStart, size_t nLen,
+ const wxStringBase& str,
+ size_t nStart2, size_t nLen2)
+{
+ return replace(nStart, nLen, str.substr(nStart2, nLen2));
+}
+
+wxStringBase& wxStringBase::replace(size_t nStart, size_t nLen,
+ const wxChar* sz, size_t nCount)
+{
+ return replace(nStart, nLen, wxStringBase(sz, nCount).c_str());
+}
+
+wxStringBase wxStringBase::substr(size_t nStart, size_t nLen) const
+{
+ if ( nLen == npos )
+ nLen = length() - nStart;
+ return wxStringBase(*this, nStart, nLen);