+ 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 wxMemcmp(s1, s2, l1);
+ else if( l1 < l2 )
+ {
+ int ret = wxMemcmp(s1, s2, l1);
+ return ret == 0 ? -1 : ret;
+ }
+ else if( l1 > l2 )
+ {
+ int ret = wxMemcmp(s1, s2, l2);
+ return ret == 0 ? +1 : ret;
+ }
+
+ wxFAIL; // must never get there
+ return 0; // quiet compilers
+}
+
+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
+// ===========================================================================
+
+// ---------------------------------------------------------------------------
+// common conversion routines
+// ---------------------------------------------------------------------------
+
+size_t wxString::WorstEncodingCase(size_t len, const wxMBConv& WXUNUSED(conv))
+{
+ //Worst case for UTF7
+ return len * 5;
+}
+
+#if wxUSE_WCHAR_T
+
+//Convert a wide character string of a specified length
+//to a multi-byte character string, ignoring intermittent null characters
+//returns the actual length of the string
+inline size_t wxMbstr(char* szBuffer, const wchar_t* szString,
+ size_t nStringLen, wxMBConv& conv)
+{
+ const wchar_t* szEnd = szString + nStringLen + 1;
+ const wchar_t* szPos = szString;
+ const wchar_t* szStart = szPos;
+
+ size_t nActualLength = 0;
+
+ //Convert the string until the length() is reached, continuing the
+ //loop every time a null character is reached
+ while(szPos != szEnd)
+ {
+ wxASSERT(szPos < szEnd); //something is _really_ screwed up if this rings true
+
+ //Get the length of the current (sub)string
+ size_t nLen = conv.WC2MB(NULL, szPos, 0);
+
+ //Invalid conversion?
+ if( nLen == (size_t)-1 )
+ {
+ szBuffer[0] = '\0';
+ return 0;
+ }
+
+ //Increase the actual length (+1 for current null character)
+ nActualLength += nLen + 1;
+
+ //If this is true it means buffer overflow
+ wxASSERT( nActualLength <= wxString::WorstEncodingCase(nStringLen, conv) + 1 );
+
+ //Convert the current (sub)string
+ if(conv.WC2MB(&szBuffer[szPos - szStart], szPos, nLen + 1) == (size_t)-1 )
+ {
+ //error - return empty buffer
+ wxFAIL_MSG(wxT("Error converting wide-character string to a multi-byte string"));
+ szBuffer[0] = '\0';
+ return 0;
+ }
+
+ //Increment to next (sub)string
+ //Note that we have to use wxWcslen here instead of nLen
+ //here because XX2XX gives us the size of the output buffer,
+ //not neccessarly the length of the string
+ szPos += wxWcslen(szPos) + 1;
+ }
+
+ return nActualLength - 1; //success - return actual length
+}
+
+//Convert a multi-byte character string of a specified length
+//to a wide character string, ignoring intermittent null characters
+//returns the actual length
+inline size_t wxWcstr( wchar_t* szBuffer, const char* szString,
+ size_t nStringLen, wxMBConv& conv)
+{
+ const char* szEnd = szString + nStringLen + 1;
+ const char* szPos = szString;
+ const char* szStart = szPos;
+
+ size_t nActualLength = 0;
+
+ //Convert the string until the length() is reached, continuing the
+ //loop every time a null character is reached
+ while(szPos != szEnd)
+ {
+ wxASSERT(szPos < szEnd); //something is _really_ screwed up if this rings true
+
+ //Get the length of the current (sub)string
+ size_t nLen = conv.MB2WC(NULL, szPos, 0);
+
+ //Invalid conversion?
+ if( nLen == (size_t)-1 )
+ {
+ szBuffer[0] = '\0';
+ return 0;
+ }
+
+ //Increase the actual length (+1 for current null character)
+ nActualLength += nLen + 1;
+
+ //If this is true it means buffer overflow
+ wxASSERT(nActualLength <= nStringLen + 1);
+
+ //Convert the current (sub)string
+ if ( conv.MB2WC(&szBuffer[szPos - szStart], szPos, nLen + 1) == (size_t)-1 )
+ {
+ //error - return empty buffer
+ wxFAIL_MSG(wxT("Error converting multi-byte string to a wide-character string"));
+ szBuffer[0] = '\0';
+ return 0;
+ }
+
+ //Increment to next (sub)string
+ //Note that we have to use strlen here instead of nLen
+ //here because XX2XX gives us the size of the output buffer,
+ //not neccessarly the length of the string
+ szPos += strlen(szPos) + 1;
+ }
+
+ return nActualLength - 1; //success - return actual length
+}
+
+#endif //wxUSE_WCHAR_T
+
+// ---------------------------------------------------------------------------
+// construction and conversion
+// ---------------------------------------------------------------------------
+
+#if wxUSE_UNICODE
+
+// 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)
+ {
+ 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) )
+ {
+ //When converting mb->wc it never inflates to more characters than the length
+ wxStringBufferLength internalBuffer(*this, nLen + 1);
+
+ //Do the actual conversion & Set the length of the buffer
+ internalBuffer.SetLength(
+ wxWcstr(internalBuffer, psz, nLen, conv)
+ );
+ }
+}
+
+//Convert wxString in Unicode mode to a multi-byte string
+const wxCharBuffer wxString::mb_str(wxMBConv& conv) const
+{
+ //Create the buffer
+ wxCharBuffer buffer( wxString::WorstEncodingCase(length(), conv) + 1);
+
+ //Do the actual conversion (will return a blank string on error)
+ wxMbstr(buffer.data(), (*this).c_str(), length(), conv);
+
+ return buffer;