- 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
-
- //This is kind of inefficient, but its pretty good considering...
- //we don't want to use character access operators here because on STL
- //it will freeze the reference count of strTmp, which means a deep copy
- //at the end when swap is called
- //
- //Also, we can't use append with the full character pointer and must
- //do it manually because this string can contain null characters
- for(size_t i1 = 0; i1 < nStart; ++i1)
- strTmp.append(1, this->c_str()[i1]);
-
- //its safe to do the full version here because
- //sz must be a normal c string
- strTmp.append(sz);
-
- for(size_t i2 = nStart + nLen; i2 < length(); ++i2)
- strTmp.append(1, this->c_str()[i2]);
-
- swap(strTmp);
- return *this;
-}
-
-wxStringBase& wxStringBase::replace(size_t nStart, size_t nLen,
- size_t nCount, wxChar ch)
-{
- return replace(nStart, nLen, wxStringBase(nCount, ch).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);
-}
-
-// assigns one string to another
-wxStringBase& wxStringBase::operator=(const wxStringBase& stringSrc)
-{
- wxASSERT( stringSrc.GetStringData()->IsValid() );
-
- // don't copy string over itself
- if ( m_pchData != stringSrc.m_pchData ) {
- if ( stringSrc.GetStringData()->IsEmpty() ) {
- Reinit();
- }
- else {
- // adjust references
- GetStringData()->Unlock();
- m_pchData = stringSrc.m_pchData;
- GetStringData()->Lock();
- }
- }
-
- return *this;
-}
-
-// assigns a single character
-wxStringBase& wxStringBase::operator=(wxChar ch)
-{
- if ( !AssignCopy(1, &ch) ) {
- wxFAIL_MSG( _T("out of memory in wxStringBase::operator=(wxChar)") );
- }
- return *this;
-}
-
-// assigns C string
-wxStringBase& wxStringBase::operator=(const wxChar *psz)
-{
- if ( !AssignCopy(wxStrlen(psz), psz) ) {
- wxFAIL_MSG( _T("out of memory in wxStringBase::operator=(const wxChar *)") );
- }
- return *this;
-}
-
-// helper function: does real copy
-bool wxStringBase::AssignCopy(size_t nSrcLen, const wxChar *pszSrcData)
-{
- if ( nSrcLen == 0 ) {
- Reinit();
- }
- else {
- if ( !AllocBeforeWrite(nSrcLen) ) {
- // allocation failure handled by caller
- return false;
- }
- memcpy(m_pchData, pszSrcData, nSrcLen*sizeof(wxChar));
- GetStringData()->nDataLength = nSrcLen;
- m_pchData[nSrcLen] = wxT('\0');
- }
- return true;
-}
-
-// ---------------------------------------------------------------------------
-// string concatenation
-// ---------------------------------------------------------------------------
-
-// add something to this string
-bool wxStringBase::ConcatSelf(size_t nSrcLen, const wxChar *pszSrcData,
- size_t nMaxLen)
-{
- STATISTICS_ADD(SummandLength, nSrcLen);
-
- nSrcLen = nSrcLen < nMaxLen ? nSrcLen : nMaxLen;
-
- // concatenating an empty string is a NOP
- if ( nSrcLen > 0 ) {
- wxStringData *pData = GetStringData();
- size_t nLen = pData->nDataLength;
- size_t nNewLen = nLen + nSrcLen;
-
- // alloc new buffer if current is too small
- if ( pData->IsShared() ) {
- STATISTICS_ADD(ConcatHit, 0);
-
- // we have to allocate another buffer
- wxStringData* pOldData = GetStringData();
- if ( !AllocBuffer(nNewLen) ) {
- // allocation failure handled by caller
- return false;
- }
- memcpy(m_pchData, pOldData->data(), nLen*sizeof(wxChar));
- pOldData->Unlock();
- }
- else if ( nNewLen > pData->nAllocLength ) {
- STATISTICS_ADD(ConcatHit, 0);
-
- reserve(nNewLen);
- // we have to grow the buffer
- if ( capacity() < nNewLen ) {
- // allocation failure handled by caller
- return false;
- }
- }
- else {
- STATISTICS_ADD(ConcatHit, 1);
-
- // the buffer is already big enough
- }
-
- // should be enough space
- wxASSERT( nNewLen <= GetStringData()->nAllocLength );
-
- // fast concatenation - all is done in our buffer
- memcpy(m_pchData + nLen, pszSrcData, nSrcLen*sizeof(wxChar));
-
- m_pchData[nNewLen] = wxT('\0'); // put terminating '\0'
- GetStringData()->nDataLength = nNewLen; // and fix the length
- }
- //else: the string to append was empty
- return true;
-}
-
-// ---------------------------------------------------------------------------
-// simple sub-string extraction
-// ---------------------------------------------------------------------------
-
-// helper function: clone the data attached to this string
-bool wxStringBase::AllocCopy(wxString& dest, int nCopyLen, int nCopyIndex) const
-{
- if ( nCopyLen == 0 ) {
- dest.Init();
- }
- else {
- if ( !dest.AllocBuffer(nCopyLen) ) {
- // allocation failure handled by caller
- return false;
- }
- memcpy(dest.m_pchData, m_pchData + nCopyIndex, nCopyLen*sizeof(wxChar));
- }
- return true;
-}
-
-#endif // !wxUSE_STL
-
-#if !wxUSE_STL || !defined(HAVE_STD_STRING_COMPARE)
-
-#if !wxUSE_STL
- #define STRINGCLASS wxStringBase
-#else
- #define STRINGCLASS wxString
-#endif
-
-static inline int wxDoCmp(const wxChar* s1, size_t l1,
- const wxChar* s2, size_t l2)
-{
- if( l1 == l2 )
- return wxTmemcmp(s1, s2, l1);
- else if( l1 < l2 )
- {
- int ret = wxTmemcmp(s1, s2, l1);
- return ret == 0 ? -1 : ret;
- }
- else
- {
- int ret = wxTmemcmp(s1, s2, l2);
- return ret == 0 ? +1 : ret;
- }
-}
-
-int STRINGCLASS::compare(const wxStringBase& str) const
-{
- return ::wxDoCmp(data(), length(), str.data(), str.length());
-}
-
-int STRINGCLASS::compare(size_t nStart, size_t nLen,
- const wxStringBase& str) const
-{
- wxASSERT(nStart <= length());
- size_type strLen = length() - nStart;
- nLen = strLen < nLen ? strLen : nLen;
- return ::wxDoCmp(data() + nStart, nLen, str.data(), str.length());
-}
-
-int STRINGCLASS::compare(size_t nStart, size_t nLen,
- const wxStringBase& str,
- size_t nStart2, size_t nLen2) const
-{
- wxASSERT(nStart <= length());
- wxASSERT(nStart2 <= str.length());
- size_type strLen = length() - nStart,
- strLen2 = str.length() - nStart2;
- nLen = strLen < nLen ? strLen : nLen;
- nLen2 = strLen2 < nLen2 ? strLen2 : nLen2;
- return ::wxDoCmp(data() + nStart, nLen, str.data() + nStart2, nLen2);
-}
-
-int STRINGCLASS::compare(const wxChar* sz) const
-{
- size_t nLen = wxStrlen(sz);
- return ::wxDoCmp(data(), length(), sz, nLen);
-}
-
-int STRINGCLASS::compare(size_t nStart, size_t nLen,
- const wxChar* sz, size_t nCount) const
-{
- wxASSERT(nStart <= length());
- size_type strLen = length() - nStart;
- nLen = strLen < nLen ? strLen : nLen;
- if( nCount == npos )
- nCount = wxStrlen(sz);
-
- return ::wxDoCmp(data() + nStart, nLen, sz, nCount);
-}
-
-#undef STRINGCLASS
-
-#endif // !wxUSE_STL || !defined(HAVE_STD_STRING_COMPARE)
-
-// ===========================================================================
-// wxString class core
-// ===========================================================================
-
-// ---------------------------------------------------------------------------
-// construction and conversion
-// ---------------------------------------------------------------------------
-
-#if wxUSE_UNICODE
-
-// from multibyte string
-wxString::wxString(const char *psz, const wxMBConv& conv, size_t nLength)
-{
- // anything to do?
- if ( psz && nLength != 0 )
- {
- if ( nLength == npos )
- {
- nLength = wxNO_LEN;
- }
-
- size_t nLenWide;
- wxWCharBuffer wbuf = conv.cMB2WC(psz, nLength, &nLenWide);
-
- if ( nLenWide )
- assign(wbuf, nLenWide);
- }
-}
-
-//Convert wxString in Unicode mode to a multi-byte string
-const wxCharBuffer wxString::mb_str(const wxMBConv& conv) const
-{
- return conv.cWC2MB(c_str(), length() + 1 /* size, not length */, NULL);
-}
-
-#else // ANSI
-
-#if wxUSE_WCHAR_T
-
-// from wide string
-wxString::wxString(const wchar_t *pwz, const wxMBConv& conv, size_t nLength)
-{
- // anything to do?
- if ( pwz && nLength != 0 )
- {
- if ( nLength == npos )
- {
- nLength = wxNO_LEN;
- }
-
- size_t nLenMB;
- wxCharBuffer buf = conv.cWC2MB(pwz, nLength, &nLenMB);
-
- if ( nLenMB )
- assign(buf, nLenMB);
- }
-}
-
-//Converts this string to a wide character string if unicode
-//mode is not enabled and wxUSE_WCHAR_T is enabled
-const wxWCharBuffer wxString::wc_str(const wxMBConv& conv) const
-{
- return conv.cMB2WC(c_str(), length() + 1 /* size, not length */, NULL);
-}
-
-#endif // wxUSE_WCHAR_T
-
-#endif // Unicode/ANSI
-
-// shrink to minimal size (releasing extra memory)
-bool wxString::Shrink()
-{
- wxString tmp(begin(), end());
- swap(tmp);
- return tmp.length() == length();
-}
-
-#if !wxUSE_STL
-// get the pointer to writable buffer of (at least) nLen bytes
-wxChar *wxString::GetWriteBuf(size_t nLen)
-{
- if ( !AllocBeforeWrite(nLen) ) {
- // allocation failure handled by caller
- return NULL;
- }
-
- wxASSERT( GetStringData()->nRefs == 1 );
- GetStringData()->Validate(false);
-
- return m_pchData;
-}
-
-// put string back in a reasonable state after GetWriteBuf
-void wxString::UngetWriteBuf()
-{
- GetStringData()->nDataLength = wxStrlen(m_pchData);
- GetStringData()->Validate(true);
-}
-
-void wxString::UngetWriteBuf(size_t nLen)
-{
- GetStringData()->nDataLength = nLen;
- GetStringData()->Validate(true);
-}
-#endif
-
-// ---------------------------------------------------------------------------
-// data access
-// ---------------------------------------------------------------------------
-
-// all functions are inline in string.h
-
-// ---------------------------------------------------------------------------
-// assignment operators
-// ---------------------------------------------------------------------------
-
-#if !wxUSE_UNICODE
-
-// same as 'signed char' variant
-wxString& wxString::operator=(const unsigned char* psz)
-{
- *this = (const char *)psz;
- return *this;
-}
-
-#if wxUSE_WCHAR_T
-wxString& wxString::operator=(const wchar_t *pwz)
-{
- wxString str(pwz);
- swap(str);
- return *this;
-}
-#endif
-
-#endif
-
-/*
- * concatenation functions come in 5 flavours:
- * string + string
- * char + string and string + char
- * C str + string and string + C str
- */
-
-wxString operator+(const wxString& str1, const wxString& str2)
-{
-#if !wxUSE_STL
- wxASSERT( str1.GetStringData()->IsValid() );
- wxASSERT( str2.GetStringData()->IsValid() );
-#endif
-
- wxString s = str1;
- s += str2;
-
- return s;
-}
-
-wxString operator+(const wxString& str, wxChar ch)
-{
-#if !wxUSE_STL
- wxASSERT( str.GetStringData()->IsValid() );
-#endif
-
- wxString s = str;
- s += ch;
-
- return s;
-}
-
-wxString operator+(wxChar ch, const wxString& str)
-{
-#if !wxUSE_STL
- wxASSERT( str.GetStringData()->IsValid() );
-#endif
-
- wxString s = ch;
- s += str;
-
- return s;
-}
-
-wxString operator+(const wxString& str, const wxChar *psz)
-{
-#if !wxUSE_STL
- wxASSERT( str.GetStringData()->IsValid() );
-#endif
-
- wxString s;
- if ( !s.Alloc(wxStrlen(psz) + str.length()) ) {
- wxFAIL_MSG( _T("out of memory in wxString::operator+") );
- }
- s += str;
- s += psz;
-
- return s;
-}
-
-wxString operator+(const wxChar *psz, const wxString& str)
-{
-#if !wxUSE_STL
- wxASSERT( str.GetStringData()->IsValid() );
-#endif
-
- wxString s;
- if ( !s.Alloc(wxStrlen(psz) + str.length()) ) {
- wxFAIL_MSG( _T("out of memory in wxString::operator+") );
- }
- s = psz;
- s += str;
-
- return s;
-}
-
-// ===========================================================================
-// other common string functions
-// ===========================================================================
-
-int wxString::Cmp(const wxString& s) const
-{
- return compare(s);
-}
-
-int wxString::Cmp(const wxChar* psz) const
-{
- return compare(psz);
-}
-
-static inline int wxDoCmpNoCase(const wxChar* s1, size_t l1,
- const wxChar* s2, size_t l2)
-{
- size_t i;
-
- if( l1 == l2 )
- {
- for(i = 0; i < l1; ++i)
- {
- if(wxTolower(s1[i]) != wxTolower(s2[i]))
- break;
- }
- return i == l1 ? 0 : wxTolower(s1[i]) < wxTolower(s2[i]) ? -1 : 1;
- }
- else if( l1 < l2 )
- {
- for(i = 0; i < l1; ++i)
- {
- if(wxTolower(s1[i]) != wxTolower(s2[i]))
- break;
- }
- return i == l1 ? -1 : wxTolower(s1[i]) < wxTolower(s2[i]) ? -1 : 1;
- }
- else
- {
- for(i = 0; i < l2; ++i)
- {
- if(wxTolower(s1[i]) != wxTolower(s2[i]))
- break;
- }
- return i == l2 ? 1 : wxTolower(s1[i]) < wxTolower(s2[i]) ? -1 : 1;