X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/93c83507aaee06567f754b976fbc16b813a30b9c..b6a20a20d010d643e52914f51aa0700df0da925f:/src/common/string.cpp diff --git a/src/common/string.cpp b/src/common/string.cpp index 4715f63154..ffddc7611e 100644 --- a/src/common/string.cpp +++ b/src/common/string.cpp @@ -100,6 +100,8 @@ extern const wxChar WXDLLIMPEXP_BASE *wxEmptyString = &g_strEmpty.dummy; // // ATTN: you can _not_ use both of these in the same program! +#include + wxSTD istream& operator>>(wxSTD istream& is, wxString& WXUNUSED(str)) { #if 0 @@ -168,6 +170,8 @@ wxSTD ostream& operator<<(wxSTD ostream& os, const wxString& str) #define STATISTICS_ADD(av, val) #endif // WXSTRING_STATISTICS +#if !wxUSE_STL + // =========================================================================== // wxStringData class deallocation // =========================================================================== @@ -180,8 +184,6 @@ void wxStringData::Free() } #endif -#if !wxUSE_STL - // =========================================================================== // wxStringBase // =========================================================================== @@ -405,6 +407,20 @@ bool wxStringBase::Alloc(size_t nLen) //else: we've already got enough return TRUE; } + +wxStringBase::iterator wxStringBase::begin() +{ + if (length() > 0) + CopyBeforeWrite(); + return m_pchData; +} + +wxStringBase::iterator wxStringBase::end() +{ + if (length() > 0) + CopyBeforeWrite(); + return m_pchData + length(); +} wxStringBase::iterator wxStringBase::erase(iterator it) { @@ -479,18 +495,35 @@ size_t wxStringBase::find(wxChar ch, size_t nStart) const 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--; - } + wxASSERT( str.GetStringData()->IsValid() ); + wxASSERT( nStart == npos || nStart <= length() ); - return npos; + 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 @@ -530,11 +563,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 +581,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 +590,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 +611,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 +637,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 +653,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(); @@ -905,12 +962,25 @@ int STRINGCLASS::compare(size_t nStart, size_t nLen, // from multibyte string wxString::wxString(const char *psz, wxMBConv& conv, size_t nLength) { + // if nLength != npos, then we have to make a NULL-terminated copy + // of first nLength bytes of psz first because the input buffer to MB2WC + // must always be NULL-terminated: + wxCharBuffer inBuf((const char *)NULL); + if (nLength != npos) + { + wxCharBuffer tmp(nLength); + memcpy(tmp.data(), psz, nLength); + tmp.data()[nLength] = '\0'; + inBuf = tmp; + psz = inBuf.data(); + } + // first get the size of the buffer we need size_t nLen; if ( psz ) { // calculate the needed size ourselves or use the provided one - nLen = nLength == npos ? conv.MB2WC(NULL, psz, 0) : nLength; + nLen = conv.MB2WC(NULL, psz, 0); } else { @@ -927,7 +997,7 @@ wxString::wxString(const char *psz, wxMBConv& conv, size_t nLength) } else { - wxWCharBuffer buf(nLen + 1); + wxWCharBuffer buf(nLen); // MB2WC wants the buffer size, not the string length hence +1 nLen = conv.MB2WC(buf.data(), psz, nLen + 1); @@ -949,12 +1019,25 @@ wxString::wxString(const char *psz, wxMBConv& conv, size_t nLength) // from wide string wxString::wxString(const wchar_t *pwz, wxMBConv& conv, size_t nLength) { + // if nLength != npos, then we have to make a NULL-terminated copy + // of first nLength chars of psz first because the input buffer to WC2MB + // must always be NULL-terminated: + wxWCharBuffer inBuf((const wchar_t *)NULL); + if (nLength != npos) + { + wxWCharBuffer tmp(nLength); + memcpy(tmp.data(), pwz, nLength * sizeof(wchar_t)); + tmp.data()[nLength] = '\0'; + inBuf = tmp; + pwz = inBuf.data(); + } + // first get the size of the buffer we need size_t nLen; if ( pwz ) { // calculate the needed size ourselves or use the provided one - nLen = nLength == npos ? conv.WC2MB(NULL, pwz, 0) : nLength; + nLen = conv.WC2MB(NULL, pwz, 0); } else { @@ -1644,7 +1727,10 @@ int wxString::PrintfV(const wxChar* pszFormat, va_list argptr) buf[size] = _T('\0'); } - if ( len >= 0 ) + // vsnprintf() may return either -1 (traditional Unix behaviour) or the + // total number of characters which would have been written if the + // buffer were large enough + if ( len >= 0 && len <= size ) { // ok, there was enough space break; @@ -2135,6 +2221,30 @@ void wxArrayString::Insert(const wxString& str, size_t nIndex, size_t nInsert) m_nCount += nInsert; } +// range insert (STL 23.2.4.3) +void +wxArrayString::insert(iterator it, const_iterator first, const_iterator last) +{ + const int idx = it - begin(); + + // grow it once + Grow(last - first); + + // reset "it" since it can change inside Grow() + it = begin() + idx; + + while ( first != last ) + { + it = insert(it, *first); + + // insert returns an iterator to the last element inserted but we need + // insert the next after this one, that is before the next one + ++it; + + ++first; + } +} + // expand the array void wxArrayString::SetCount(size_t count) { @@ -2172,6 +2282,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 // ---------------------------------------------------------------------------- @@ -2274,12 +2391,12 @@ bool wxArrayString::operator==(const wxArrayString& a) const #endif // !wxUSE_STL -int wxStringSortAscending(wxString* s1, wxString* s2) +int wxCMPFUNC_CONV wxStringSortAscending(wxString* s1, wxString* s2) { return wxStrcmp(s1->c_str(), s2->c_str()); } -int wxStringSortDescending(wxString* s1, wxString* s2) +int wxCMPFUNC_CONV wxStringSortDescending(wxString* s1, wxString* s2) { return -wxStrcmp(s1->c_str(), s2->c_str()); }