// 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
// 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
// ----------------------------------------------------------------------------
// 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"),
// 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);
}
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);
}
else
{
- wxFAIL_MSG( _T("first must be before last") );
+ wxFAIL_MSG( wxT("first must be before last") );
Init();
}
}
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;
wxStringData *pData = GetStringData();
if ( pData->nAllocLength <= nLen ) {
if ( pData->IsEmpty() ) {
+ STATISTICS_ADD(Length, nLen);
+
nLen += EXTRA_ALLOC;
pData = (wxStringData *)
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();
}
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;
}
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
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 )
{
{
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;
}
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;
}
// 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');
}
{
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);
}