+ 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 wxStrncmp(s1, s2, l1);
+ else if( l1 < l2 )
+ {
+ int ret = wxStrncmp(s1, s2, l1);
+ return ret == 0 ? -1 : ret;
+ }
+ else if( l1 > l2 )
+ {
+ int ret = wxStrncmp(s1, s2, l2);
+ return ret == 0 ? +1 : ret;
+ }
+
+ wxFAIL; // must never get there
+ return 0; // quiet compilers
+}
+
+#if wxUSE_STL
+
+int STRINGCLASS::compare(const wxStringBase& str) const
+{
+ return ::wxDoCmp(data(), length(), str.data(), str.length());
+}
+
+#endif
+
+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);
+}
+
+#if wxUSE_STL
+
+int STRINGCLASS::compare(const wxChar* sz) const
+{
+ size_t nLen = wxStrlen(sz);
+ return ::wxDoCmp(data(), length(), sz, nLen);
+}
+
+#endif
+
+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
+// ---------------------------------------------------------------------------
+
+#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
+ nLen = conv.MB2WC(NULL, psz, 0);
+ }
+ else
+ {
+ // nothing to convert
+ nLen = 0;
+ }
+
+ // anything to do?
+ if ( (nLen != 0) && (nLen != (size_t)-1) )
+ {
+ if ( !Alloc(nLen) )
+ {
+ wxFAIL_MSG( _T("out of memory in wxString::wxString") );
+ }
+ else
+ {
+ wxWCharBuffer buf(nLen);
+ // MB2WC wants the buffer size, not the string length hence +1
+ nLen = conv.MB2WC(buf.data(), psz, nLen + 1);
+
+ if ( nLen != (size_t)-1 )
+ {
+ // initialized ok, set the real length as nLength specified by
+ // the caller could be greater than the real string length
+ assign(buf.data(), nLen);
+ return;
+ }
+ //else: the conversion failed -- leave the string empty (what else?)
+ }
+ }
+}
+
+#else // ANSI
+
+#if wxUSE_WCHAR_T
+// from wide string
+wxString::wxString(const wchar_t *pwz, 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
+ nLen = conv.WC2MB(NULL, pwz, 0);
+ }
+ else
+ {
+ // nothing to convert
+ nLen = 0;
+ }
+
+ // anything to do?
+ if ( (nLen != 0) && (nLen != (size_t)-1) )
+ {
+ if ( !Alloc(nLen) )
+ {
+ wxFAIL_MSG( _T("out of memory in wxString::wxString") );
+ }
+ else
+ {
+ wxCharBuffer buf(nLen);
+ // WC2MB wants the buffer size, not the string length
+ if ( conv.WC2MB(buf.data(), pwz, nLen + 1) != (size_t)-1 )
+ {
+ // initialized ok
+ assign(buf.data(), nLen);
+ return;
+ }
+ //else: the conversion failed -- leave the string empty (what else?)
+ }
+ }
+
+ // leave empty
+}
+#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();