/////////////////////////////////////////////////////////////////////////////
-// Name: string.cpp
+// Name: src/common/string.cpp
// Purpose: wxString class
// Author: Vadim Zeitlin, Ryan Norton
// Modified by:
#include "wx/wxprec.h"
#ifdef __BORLANDC__
- #pragma hdrstop
+ #pragma hdrstop
#endif
#ifndef WX_PRECOMP
- #include "wx/defs.h"
- #include "wx/string.h"
- #include "wx/intl.h"
- #include "wx/thread.h"
+ #include "wx/string.h"
+ #include "wx/intl.h"
+ #include "wx/thread.h"
#endif
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
-#ifndef __WXMSW__
-#include <errno.h>
-#endif
-
#ifdef __SALFORDC__
- #include <clib.h>
+ #include <clib.h>
#endif
// allocating extra space for each string consumes more memory but speeds up
wxSTD ostream& operator<<(wxSTD ostream& os, const wxString& str)
{
- os << str.c_str();
- return os;
+#ifdef __BORLANDC__
+ os << str.mb_str();
+#else
+ os << str.c_str();
+#endif
+ return os;
}
#endif // wxUSE_STD_IOSTREAM
if ( pData->IsEmpty() ) {
nLen += EXTRA_ALLOC;
- wxStringData* pData = (wxStringData*)
- malloc(sizeof(wxStringData) + (nLen + 1)*sizeof(wxChar));
+ pData = (wxStringData *)
+ malloc(sizeof(wxStringData) + (nLen + 1)*sizeof(wxChar));
if ( pData == NULL ) {
// allocation failure handled by caller
wxStringBase& wxStringBase::erase(size_t nStart, size_t nLen)
{
- wxASSERT(nStart <= length());
- size_t strLen = length() - nStart;
- // delete nLen or up to the end of the string characters
- nLen = strLen < nLen ? strLen : nLen;
- wxString strTmp(c_str(), nStart);
- strTmp.append(c_str() + nStart + nLen, length() - nStart - nLen);
+ wxASSERT(nStart <= length());
+ size_t strLen = length() - nStart;
+ // delete nLen or up to the end of the string characters
+ nLen = strLen < nLen ? strLen : nLen;
+ wxString strTmp(c_str(), nStart);
+ strTmp.append(c_str() + nStart + nLen, length() - nStart - nLen);
- swap(strTmp);
- return *this;
+ swap(strTmp);
+ return *this;
}
wxStringBase& wxStringBase::insert(size_t nPos, const wxChar *sz, size_t n)
{
- wxASSERT( nPos <= length() );
+ wxASSERT( nPos <= length() );
- if ( n == npos ) n = wxStrlen(sz);
- if ( n == 0 ) return *this;
+ if ( n == npos ) n = wxStrlen(sz);
+ if ( n == 0 ) return *this;
- if ( !Alloc(length() + n) || !CopyBeforeWrite() ) {
- wxFAIL_MSG( _T("out of memory in wxStringBase::insert") );
- }
+ if ( !Alloc(length() + n) || !CopyBeforeWrite() ) {
+ wxFAIL_MSG( _T("out of memory in wxStringBase::insert") );
+ }
- memmove(m_pchData + nPos + n, m_pchData + nPos,
- (length() - nPos) * sizeof(wxChar));
- memcpy(m_pchData + nPos, sz, n * sizeof(wxChar));
- GetStringData()->nDataLength = length() + n;
- m_pchData[length()] = '\0';
+ memmove(m_pchData + nPos + n, m_pchData + nPos,
+ (length() - nPos) * sizeof(wxChar));
+ memcpy(m_pchData + nPos, sz, n * sizeof(wxChar));
+ GetStringData()->nDataLength = length() + n;
+ m_pchData[length()] = '\0';
- return *this;
+ return *this;
}
void wxStringBase::swap(wxStringBase& str)
size_t wxStringBase::find(const wxStringBase& str, size_t nStart) const
{
- wxASSERT( str.GetStringData()->IsValid() );
- wxASSERT( nStart <= length() );
+ wxASSERT( str.GetStringData()->IsValid() );
+ wxASSERT( nStart <= length() );
- //anchor
- const wxChar* p = (const wxChar*)wxTmemchr(c_str() + nStart,
- str.c_str()[0],
- length() - nStart);
+ //anchor
+ const wxChar* p = (const wxChar*)wxTmemchr(c_str() + nStart,
+ str.c_str()[0],
+ length() - nStart);
- if(!p)
- return npos;
+ if(!p)
+ return npos;
- while(p - c_str() + str.length() <= length() &&
- wxTmemcmp(p, str.c_str(), str.length()) )
- {
- //Previosly passed as the first argument to wxTmemchr,
- //but C/C++ standard does not specify evaluation order
- //of arguments to functions -
- //http://embedded.com/showArticle.jhtml?articleID=9900607
- ++p;
-
- //anchor again
- p = (const wxChar*)wxTmemchr(p,
- str.c_str()[0],
- length() - (p - c_str()));
-
- if(!p)
- return npos;
- }
+ while(p - c_str() + str.length() <= length() &&
+ wxTmemcmp(p, str.c_str(), str.length()) )
+ {
+ //Previosly passed as the first argument to wxTmemchr,
+ //but C/C++ standard does not specify evaluation order
+ //of arguments to functions -
+ //http://embedded.com/showArticle.jhtml?articleID=9900607
+ ++p;
+
+ //anchor again
+ p = (const wxChar*)wxTmemchr(p,
+ str.c_str()[0],
+ length() - (p - c_str()));
- return (p - c_str() + str.length() <= length()) ? p - c_str() : npos;
+ if(!p)
+ return npos;
+ }
+
+ return (p - c_str() + str.length() <= length()) ? p - c_str() : npos;
}
size_t wxStringBase::find(const wxChar* sz, size_t nStart, size_t n) const
{
- return find(wxStringBase(sz, n), nStart);
+ return find(wxStringBase(sz, n), nStart);
}
size_t wxStringBase::find(wxChar ch, size_t nStart) const
{
- wxASSERT( nStart <= length() );
+ wxASSERT( nStart <= length() );
- const wxChar *p = (const wxChar*)wxTmemchr(c_str() + nStart, ch, length() - nStart);
+ const wxChar *p = (const wxChar*)wxTmemchr(c_str() + nStart, ch, length() - nStart);
- return p == NULL ? npos : p - c_str();
+ return p == NULL ? npos : p - c_str();
}
size_t wxStringBase::rfind(const wxStringBase& str, size_t nStart) const
//
//Also, we can't use append with the full character pointer and must
//do it manually because this string can contain null characters
- if ( nStart != 0 )
- {
- for(size_t i1 = 0; i1 < nStart; ++i1)
- strTmp.append(1, this->c_str()[i1]);
- }
-
+ 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);
#if wxUSE_UNICODE
// from multibyte string
-wxString::wxString(const char *psz, wxMBConv& conv, size_t nLength)
+wxString::wxString(const char *psz, const 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)
- {
- wxASSERT( psz != NULL );
- 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
- if (nLength == npos)
- nLen = strlen(psz);
- else
- nLen = nLength;
- }
- else
- {
- // nothing to convert
- nLen = 0;
- }
-
-
// anything to do?
- if ( (nLen != 0) && (nLen != (size_t)-1) )
+ if ( psz && nLength != 0 )
{
- //Convert string
- size_t nRealSize;
- wxWCharBuffer theBuffer = conv.cMB2WC(psz, nLen, &nRealSize);
+ if ( nLength == npos )
+ {
+ nLength = wxNO_LEN;
+ }
+
+ size_t nLenWide;
+ wxWCharBuffer wbuf = conv.cMB2WC(psz, nLength, &nLenWide);
- //Copy
- if (nRealSize)
- assign( theBuffer.data() , nRealSize - 1 );
+ if ( nLenWide )
+ assign(wbuf, nLenWide);
}
}
//Convert wxString in Unicode mode to a multi-byte string
-const wxCharBuffer wxString::mb_str(wxMBConv& conv) const
+const wxCharBuffer wxString::mb_str(const wxMBConv& conv) const
{
- size_t dwOutSize;
- return conv.cWC2MB(c_str(), length(), &dwOutSize);
+ 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, wxMBConv& conv, size_t nLength)
+wxString::wxString(const wchar_t *pwz, const 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)
- {
- wxASSERT( pwz != NULL );
- 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
- if (nLength == npos)
- nLen = wxWcslen(pwz);
- else
- nLen = nLength;
- }
- else
- {
- // nothing to convert
- nLen = 0;
- }
-
// anything to do?
- if ( (nLen != 0) && (nLen != (size_t)-1) )
+ if ( pwz && nLength != 0 )
{
- //Convert string
- size_t nRealSize;
- wxCharBuffer theBuffer = conv.cWC2MB(pwz, nLen, &nRealSize);
+ if ( nLength == npos )
+ {
+ nLength = wxNO_LEN;
+ }
+
+ size_t nLenMB;
+ wxCharBuffer buf = conv.cWC2MB(pwz, nLength, &nLenMB);
- //Copy
- if (nRealSize)
- assign( theBuffer.data() , nRealSize - 1 );
+ 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(wxMBConv& conv) const
+const wxWCharBuffer wxString::wc_str(const wxMBConv& conv) const
{
- size_t dwOutSize;
- return conv.cMB2WC(c_str(), length(), &dwOutSize);
+ return conv.cMB2WC(c_str(), length() + 1 /* size, not length */, NULL);
}
#endif // wxUSE_WCHAR_T
// extract string of length nCount starting at nFirst
wxString wxString::Mid(size_t nFirst, size_t nCount) const
{
- size_t nLen = length();
+ size_t nLen = length();
- // default value of nCount is npos and means "till the end"
- if ( nCount == npos )
- {
- nCount = nLen - nFirst;
- }
+ // default value of nCount is npos and means "till the end"
+ if ( nCount == npos )
+ {
+ nCount = nLen - nFirst;
+ }
- // out-of-bounds requests return sensible things
- if ( nFirst + nCount > nLen )
- {
- nCount = nLen - nFirst;
- }
+ // out-of-bounds requests return sensible things
+ if ( nFirst + nCount > nLen )
+ {
+ nCount = nLen - nFirst;
+ }
- if ( nFirst > nLen )
- {
- // AllocCopy() will return empty string
- nCount = 0;
- }
+ if ( nFirst > nLen )
+ {
+ // AllocCopy() will return empty string
+ return wxEmptyString;
+ }
- wxString dest(*this, nFirst, nCount);
- if ( dest.length() != nCount ) {
- wxFAIL_MSG( _T("out of memory in wxString::Mid") );
- }
+ wxString dest(*this, nFirst, nCount);
+ if ( dest.length() != nCount )
+ {
+ wxFAIL_MSG( _T("out of memory in wxString::Mid") );
+ }
- return dest;
+ return dest;
}
// check that the string starts with prefix and return the rest of the string
}
// replace first (or all) occurences of some substring with another one
-size_t wxString::Replace(const wxChar *szOld,
+size_t wxString::Replace(const wxChar *szOld,
const wxChar *szNew, bool bReplaceAll)
{
// if we tried to replace an empty string we'd enter an infinite loop below
size_t dwPos = 0;
- while ( this->c_str()[dwPos] != wxT('\0') )
+ while ( this->c_str()[dwPos] != wxT('\0') )
{
//DO NOT USE STRSTR HERE
//this string can contain embedded null characters,
//so strstr will function incorrectly
dwPos = find(szOld, dwPos);
- if ( dwPos == npos )
+ if ( dwPos == npos )
break; // exit the loop
- else
+ else
{
//replace this occurance of the old string with the new one
replace(dwPos, uiOldLen, szNew, uiNewLen);
- //move up pos past the old string
- dwPos += uiOldLen;
+ //move up pos past the string that was replaced
+ dwPos += uiNewLen;
//increase replace count
++uiCount;
-
+
// stop now?
- if ( !bReplaceAll )
+ if ( !bReplaceAll )
break; // exit the loop
}
}
for ( ;; )
{
wxStringBuffer tmp(*this, size + 1);
- wxChar* buf = tmp;
+ wxChar *buf = tmp;
if ( !buf )
{
// 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
- // also, it may return an errno may be something like EILSEQ,
- // in which case we need to break out
- if ( (len >= 0 && len <= size)
- // No EOVERFLOW on Windows nor Palm 6.0 nor OpenVMS nor MacOS (not X)
- // not OS/2 (not Innotek libc).
-#if !defined(__WXMSW__) && !defined(__WXPALMOS__) && !defined( __VMS ) && !(defined(__WXMAC__) && !defined(__WXMAC_OSX__)) && !(defined(__EMX__) && !defined(__INNOTEK_LIBC__))
- || errno != EOVERFLOW
-#endif
- )
+ // buffer were large enough (newer standards such as Unix98)
+ if ( len < 0 )
+ {
+ // still not enough, as we don't know how much we need, double the
+ // current size of the buffer
+ size *= 2;
+ }
+ else if ( len > size )
+ {
+ size = len;
+ }
+ else // ok, there was enough space
{
- // ok, there was enough space
break;
}
-
- // still not enough, double it again
- size *= 2;
}
// we could have overshot
END_SORT();
}
-typedef int (wxC_CALLING_CONV * wxStringCompareFn)(const void *first, const void *second);
+extern "C"
+{
+ typedef int (wxC_CALLING_CONV * wxStringCompareFn)(const void *first,
+ const void *second);
+}
void wxArrayString::Sort(CompareFunction2 compareFunction)
{