X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/dfaae3e640da198acdb53394c1a4110b76431c77..bc9d3d911cfb51f612a699d7fb00f57eb5b2097c:/src/common/stringimpl.cpp diff --git a/src/common/stringimpl.cpp b/src/common/stringimpl.cpp index c8799442c3..498793722e 100644 --- a/src/common/stringimpl.cpp +++ b/src/common/stringimpl.cpp @@ -42,10 +42,6 @@ #include #include -#ifdef __SALFORDC__ - #include -#endif - // allocating extra space for each string consumes more memory but speeds up // the concatenation operations (nLen is the current string's length) // NB: EXTRA_ALLOC must be >= 0! @@ -81,9 +77,9 @@ const size_t wxStringImpl::npos = (size_t) -1; // FIXME-UTF8: get rid of this, have only one wxEmptyString #if wxUSE_UNICODE_UTF8 -extern const wxStringCharType WXDLLIMPEXP_BASE *wxEmptyStringImpl = ""; +const wxStringCharType WXDLLIMPEXP_BASE *wxEmptyStringImpl = ""; #endif -extern const wxChar WXDLLIMPEXP_BASE *wxEmptyString = _T(""); +const wxChar WXDLLIMPEXP_BASE *wxEmptyString = wxT(""); #else @@ -99,10 +95,10 @@ static const struct // empty C style string: points to 'string data' byte of g_strEmpty #if wxUSE_UNICODE_UTF8 // FIXME-UTF8: get rid of this, have only one wxEmptyString -extern const wxStringCharType WXDLLIMPEXP_BASE *wxEmptyStringImpl = &g_strEmpty.dummy; -extern const wxChar WXDLLIMPEXP_BASE *wxEmptyString = _T(""); +const wxStringCharType WXDLLIMPEXP_BASE *wxEmptyStringImpl = &g_strEmpty.dummy; +const wxChar WXDLLIMPEXP_BASE *wxEmptyString = wxT(""); #else -extern const wxStringCharType WXDLLIMPEXP_BASE *wxEmptyString = &g_strEmpty.dummy; +const wxStringCharType WXDLLIMPEXP_BASE *wxEmptyString = &g_strEmpty.dummy; #endif #endif @@ -115,19 +111,26 @@ extern const wxStringCharType WXDLLIMPEXP_BASE *wxEmptyString = &g_strEmpty.dumm // ---------------------------------------------------------------------------- // this small class is used to gather statistics for performance tuning + +// uncomment this to enable gathering of some statistics about wxString +// efficiency //#define WXSTRING_STATISTICS + #ifdef WXSTRING_STATISTICS class Averager { public: Averager(const wxStringCharType *sz) { m_sz = sz; m_nTotal = m_nCount = 0; } ~Averager() - { wxPrintf("wxString: average %s = %f\n", m_sz, ((float)m_nTotal)/m_nCount); } + { + wxPrintf("wxString %s: total = %lu, average = %f\n", + m_sz, m_nTotal, ((float)m_nTotal)/m_nCount); + } void Add(size_t n) { m_nTotal += n; m_nCount++; } private: - size_t m_nCount, m_nTotal; + unsigned long m_nCount, m_nTotal; const wxStringCharType *m_sz; } g_averageLength("allocation size"), g_averageSummandLength("summand length"), @@ -163,7 +166,7 @@ void wxStringImpl::InitWith(const wxStringCharType *psz, // if the length is not given, assume the string to be NUL terminated if ( nLength == npos ) { - wxASSERT_MSG( nPos <= wxStrlen(psz), _T("index out of bounds") ); + wxASSERT_MSG( nPos <= wxStrlen(psz), wxT("index out of bounds") ); nLength = wxStrlen(psz + nPos); } @@ -173,7 +176,7 @@ void wxStringImpl::InitWith(const wxStringCharType *psz, if ( nLength > 0 ) { // trailing '\0' is written in AllocBuffer() if ( !AllocBuffer(nLength) ) { - wxFAIL_MSG( _T("out of memory in wxStringImpl::InitWith") ); + wxFAIL_MSG( wxT("out of memory in wxStringImpl::InitWith") ); return; } wxStringMemcpy(m_pchData, psz + nPos, nLength); @@ -184,11 +187,11 @@ wxStringImpl::wxStringImpl(const_iterator first, const_iterator last) { if ( last >= first ) { - InitWith(first, 0, last - first); + InitWith(first.GetPtr(), 0, last - first); } else { - wxFAIL_MSG( _T("first must be before last") ); + wxFAIL_MSG( wxT("first must be before last") ); Init(); } } @@ -211,8 +214,8 @@ bool wxStringImpl::AllocBuffer(size_t nLen) wxASSERT( nLen > 0 ); // make sure that we don't overflow - wxASSERT( nLen < (INT_MAX / sizeof(wxStringCharType)) - - (sizeof(wxStringData) + EXTRA_ALLOC + 1) ); + wxCHECK( nLen < (INT_MAX / sizeof(wxStringCharType)) - + (sizeof(wxStringData) + EXTRA_ALLOC + 1), false ); STATISTICS_ADD(Length, nLen); @@ -308,7 +311,7 @@ wxStringImpl& wxStringImpl::append(size_t n, wxStringCharType ch) size_type len = length(); if ( !Alloc(len + n) || !CopyBeforeWrite() ) { - wxFAIL_MSG( _T("out of memory in wxStringImpl::append") ); + wxFAIL_MSG( wxT("out of memory in wxStringImpl::append") ); return *this; } GetStringData()->nDataLength = len + n; @@ -339,6 +342,8 @@ bool wxStringImpl::Alloc(size_t nLen) wxStringData *pData = GetStringData(); if ( pData->nAllocLength <= nLen ) { if ( pData->IsEmpty() ) { + STATISTICS_ADD(Length, nLen); + nLen += EXTRA_ALLOC; pData = (wxStringData *) @@ -390,14 +395,14 @@ bool wxStringImpl::Alloc(size_t nLen) wxStringImpl::iterator wxStringImpl::begin() { - if (length() > 0) + if ( !empty() ) CopyBeforeWrite(); return m_pchData; } wxStringImpl::iterator wxStringImpl::end() { - if (length() > 0) + if ( !empty() ) CopyBeforeWrite(); return m_pchData + length(); } @@ -431,7 +436,7 @@ wxStringImpl& wxStringImpl::insert(size_t nPos, if ( n == 0 ) return *this; if ( !Alloc(length() + n) || !CopyBeforeWrite() ) { - wxFAIL_MSG( _T("out of memory in wxStringImpl::insert") ); + wxFAIL_MSG( wxT("out of memory in wxStringImpl::insert") ); return *this; } @@ -523,7 +528,7 @@ size_t wxStringImpl::rfind(const wxStringImpl& str, size_t nStart) const if ( length() >= str.length() ) { // avoids a corner case later - if ( length() == 0 && str.length() == 0 ) + if ( empty() && str.empty() ) return 0; // "top" is the point where search starts from @@ -582,7 +587,7 @@ wxStringImpl& wxStringImpl::replace(size_t nStart, size_t nLen, const size_t lenOld = length(); wxASSERT_MSG( nStart <= lenOld, - _T("index out of bounds in wxStringImpl::replace") ); + wxT("index out of bounds in wxStringImpl::replace") ); size_t nEnd = nStart + nLen; if ( nLen > lenOld - nStart ) { @@ -650,7 +655,7 @@ wxStringImpl& wxStringImpl::operator=(wxStringCharType ch) { wxStringCharType c(ch); if ( !AssignCopy(1, &c) ) { - wxFAIL_MSG( _T("out of memory in wxStringImpl::operator=(wxStringCharType)") ); + wxFAIL_MSG( wxT("out of memory in wxStringImpl::operator=(wxStringCharType)") ); } return *this; } @@ -659,7 +664,7 @@ wxStringImpl& wxStringImpl::operator=(wxStringCharType ch) wxStringImpl& wxStringImpl::operator=(const wxStringCharType *psz) { if ( !AssignCopy(wxStrlen(psz), psz) ) { - wxFAIL_MSG( _T("out of memory in wxStringImpl::operator=(const wxStringCharType *)") ); + wxFAIL_MSG( wxT("out of memory in wxStringImpl::operator=(const wxStringCharType *)") ); } return *this; } @@ -676,7 +681,11 @@ bool wxStringImpl::AssignCopy(size_t nSrcLen, // allocation failure handled by caller return false; } - memcpy(m_pchData, pszSrcData, nSrcLen*sizeof(wxStringCharType)); + + // use memmove() and not memcpy() here as we might be copying from our own + // buffer in case of assignment such as "s = s.c_str()" (see #11294) + memmove(m_pchData, pszSrcData, nSrcLen*sizeof(wxStringCharType)); + GetStringData()->nDataLength = nSrcLen; m_pchData[nSrcLen] = wxT('\0'); } @@ -779,10 +788,10 @@ void wxStringImpl::DoUngetWriteBuf(size_t nLen) { wxStringData * const pData = GetStringData(); - wxASSERT_MSG( nLen < pData->nAllocLength, _T("buffer overrun") ); + wxASSERT_MSG( nLen < pData->nAllocLength, wxT("buffer overrun") ); // the strings we store are always NUL-terminated - pData->data()[nLen] = _T('\0'); + pData->data()[nLen] = wxT('\0'); pData->nDataLength = nLen; pData->Validate(true); }