+ {
+ wxSTRING_INVALIDATE_CACHED_LENGTH();
+
+ m_impl.append(first.impl(), last.impl());
+ return *this;
+ }
+#if WXWIN_COMPATIBILITY_STRING_PTR_AS_ITER
+ wxString& append(const char *first, const char *last)
+ { return append(first, last - first); }
+ wxString& append(const wchar_t *first, const wchar_t *last)
+ { return append(first, last - first); }
+ wxString& append(const wxCStrData& first, const wxCStrData& last)
+ { return append(CreateConstIterator(first), CreateConstIterator(last)); }
+#endif // WXWIN_COMPATIBILITY_STRING_PTR_AS_ITER
+
+ // same as `this_string = str'
+ wxString& assign(const wxString& str)
+ {
+ wxSTRING_SET_CACHED_LENGTH(str.length());
+
+ m_impl = str.m_impl;
+
+ return *this;
+ }
+
+ wxString& assign(const wxString& str, size_t len)
+ {
+ wxSTRING_SET_CACHED_LENGTH(len);
+
+ m_impl.assign(str.m_impl, 0, str.LenToImpl(len));
+
+ return *this;
+ }
+
+ // same as ` = str[pos..pos + n]
+ wxString& assign(const wxString& str, size_t pos, size_t n)
+ {
+ size_t from, len;
+ str.PosLenToImpl(pos, n, &from, &len);
+ m_impl.assign(str.m_impl, from, len);
+
+ // it's important to call this after PosLenToImpl() above in case str is
+ // the same string as this one
+ wxSTRING_SET_CACHED_LENGTH(n);
+
+ return *this;
+ }
+
+ // same as `= first n (or all if n == npos) characters of sz'
+ wxString& assign(const char *sz)
+ {
+ wxSTRING_INVALIDATE_CACHE();
+
+ m_impl.assign(ImplStr(sz));
+
+ return *this;
+ }
+
+ wxString& assign(const wchar_t *sz)
+ {
+ wxSTRING_INVALIDATE_CACHE();
+
+ m_impl.assign(ImplStr(sz));
+
+ return *this;
+ }
+
+ wxString& assign(const char *sz, size_t n)
+ {
+ wxSTRING_SET_CACHED_LENGTH(n);
+
+ SubstrBufFromMB str(ImplStr(sz, n));
+ m_impl.assign(str.data, str.len);
+
+ return *this;
+ }
+
+ wxString& assign(const wchar_t *sz, size_t n)
+ {
+ wxSTRING_SET_CACHED_LENGTH(n);
+
+ SubstrBufFromWC str(ImplStr(sz, n));
+ m_impl.assign(str.data, str.len);
+
+ return *this;
+ }
+
+ wxString& assign(const wxCStrData& str)
+ { return assign(str.AsString()); }
+ wxString& assign(const wxScopedCharBuffer& str)
+ { return assign(str.data(), str.length()); }
+ wxString& assign(const wxScopedWCharBuffer& str)
+ { return assign(str.data(), str.length()); }
+ wxString& assign(const wxCStrData& str, size_t len)
+ { return assign(str.AsString(), len); }
+ wxString& assign(const wxScopedCharBuffer& str, size_t len)
+ { return assign(str.data(), len); }
+ wxString& assign(const wxScopedWCharBuffer& str, size_t len)
+ { return assign(str.data(), len); }
+
+ // same as `= n copies of ch'
+ wxString& assign(size_t n, wxUniChar ch)
+ {
+ wxSTRING_SET_CACHED_LENGTH(n);
+
+#if wxUSE_UNICODE_UTF8
+ if ( !ch.IsAscii() )
+ m_impl.assign(wxStringOperations::EncodeNChars(n, ch));
+ else
+#endif
+ m_impl.assign(n, (wxStringCharType)ch);
+
+ return *this;
+ }
+
+ wxString& assign(size_t n, wxUniCharRef ch)
+ { return assign(n, wxUniChar(ch)); }
+ wxString& assign(size_t n, char ch)
+ { return assign(n, wxUniChar(ch)); }
+ wxString& assign(size_t n, unsigned char ch)
+ { return assign(n, wxUniChar(ch)); }
+ wxString& assign(size_t n, wchar_t ch)
+ { return assign(n, wxUniChar(ch)); }
+
+ // assign from first to last
+ wxString& assign(const_iterator first, const_iterator last)
+ {
+ wxSTRING_INVALIDATE_CACHE();
+
+ m_impl.assign(first.impl(), last.impl());
+
+ return *this;
+ }
+#if WXWIN_COMPATIBILITY_STRING_PTR_AS_ITER
+ wxString& assign(const char *first, const char *last)
+ { return assign(first, last - first); }
+ wxString& assign(const wchar_t *first, const wchar_t *last)
+ { return assign(first, last - first); }
+ wxString& assign(const wxCStrData& first, const wxCStrData& last)
+ { return assign(CreateConstIterator(first), CreateConstIterator(last)); }
+#endif // WXWIN_COMPATIBILITY_STRING_PTR_AS_ITER
+
+ // string comparison
+ int compare(const wxString& str) const;
+ int compare(const char* sz) const;
+ int compare(const wchar_t* sz) const;
+ int compare(const wxCStrData& str) const
+ { return compare(str.AsString()); }
+ int compare(const wxScopedCharBuffer& str) const
+ { return compare(str.data()); }
+ int compare(const wxScopedWCharBuffer& str) const
+ { return compare(str.data()); }
+ // comparison with a substring
+ int compare(size_t nStart, size_t nLen, const wxString& str) const;
+ // comparison of 2 substrings
+ int compare(size_t nStart, size_t nLen,
+ const wxString& str, size_t nStart2, size_t nLen2) const;
+ // substring comparison with first nCount characters of sz
+ int compare(size_t nStart, size_t nLen,
+ const char* sz, size_t nCount = npos) const;
+ int compare(size_t nStart, size_t nLen,
+ const wchar_t* sz, size_t nCount = npos) const;
+
+ // insert another string
+ wxString& insert(size_t nPos, const wxString& str)
+ { insert(GetIterForNthChar(nPos), str.begin(), str.end()); return *this; }
+ // insert n chars of str starting at nStart (in str)
+ wxString& insert(size_t nPos, const wxString& str, size_t nStart, size_t n)
+ {
+ wxSTRING_UPDATE_CACHED_LENGTH(n);
+
+ size_t from, len;
+ str.PosLenToImpl(nStart, n, &from, &len);
+ m_impl.insert(PosToImpl(nPos), str.m_impl, from, len);
+
+ return *this;
+ }
+
+ // insert first n (or all if n == npos) characters of sz
+ wxString& insert(size_t nPos, const char *sz)
+ {
+ wxSTRING_INVALIDATE_CACHE();
+
+ m_impl.insert(PosToImpl(nPos), ImplStr(sz));
+
+ return *this;
+ }
+
+ wxString& insert(size_t nPos, const wchar_t *sz)
+ {
+ wxSTRING_INVALIDATE_CACHE();
+
+ m_impl.insert(PosToImpl(nPos), ImplStr(sz)); return *this;
+ }
+
+ wxString& insert(size_t nPos, const char *sz, size_t n)
+ {
+ wxSTRING_UPDATE_CACHED_LENGTH(n);
+
+ SubstrBufFromMB str(ImplStr(sz, n));
+ m_impl.insert(PosToImpl(nPos), str.data, str.len);
+
+ return *this;
+ }
+
+ wxString& insert(size_t nPos, const wchar_t *sz, size_t n)
+ {
+ wxSTRING_UPDATE_CACHED_LENGTH(n);
+
+ SubstrBufFromWC str(ImplStr(sz, n));
+ m_impl.insert(PosToImpl(nPos), str.data, str.len);
+
+ return *this;
+ }
+
+ // insert n copies of ch
+ wxString& insert(size_t nPos, size_t n, wxUniChar ch)
+ {
+ wxSTRING_UPDATE_CACHED_LENGTH(n);
+
+#if wxUSE_UNICODE_UTF8
+ if ( !ch.IsAscii() )
+ m_impl.insert(PosToImpl(nPos), wxStringOperations::EncodeNChars(n, ch));
+ else
+#endif
+ m_impl.insert(PosToImpl(nPos), n, (wxStringCharType)ch);
+ return *this;
+ }
+
+ iterator insert(iterator it, wxUniChar ch)
+ {
+ wxSTRING_UPDATE_CACHED_LENGTH(1);
+
+#if wxUSE_UNICODE_UTF8
+ if ( !ch.IsAscii() )
+ {
+ size_t pos = IterToImplPos(it);
+ m_impl.insert(pos, wxStringOperations::EncodeChar(ch));
+ return iterator(this, m_impl.begin() + pos);
+ }
+ else
+#endif
+ return iterator(this, m_impl.insert(it.impl(), (wxStringCharType)ch));
+ }
+
+ void insert(iterator it, const_iterator first, const_iterator last)
+ {
+ wxSTRING_INVALIDATE_CACHE();
+
+ m_impl.insert(it.impl(), first.impl(), last.impl());
+ }
+
+#if WXWIN_COMPATIBILITY_STRING_PTR_AS_ITER
+ void insert(iterator it, const char *first, const char *last)
+ { insert(it - begin(), first, last - first); }
+ void insert(iterator it, const wchar_t *first, const wchar_t *last)
+ { insert(it - begin(), first, last - first); }
+ void insert(iterator it, const wxCStrData& first, const wxCStrData& last)
+ { insert(it, CreateConstIterator(first), CreateConstIterator(last)); }
+#endif // WXWIN_COMPATIBILITY_STRING_PTR_AS_ITER
+
+ void insert(iterator it, size_type n, wxUniChar ch)
+ {
+ wxSTRING_UPDATE_CACHED_LENGTH(n);
+
+#if wxUSE_UNICODE_UTF8
+ if ( !ch.IsAscii() )
+ m_impl.insert(IterToImplPos(it), wxStringOperations::EncodeNChars(n, ch));
+ else
+#endif
+ m_impl.insert(it.impl(), n, (wxStringCharType)ch);
+ }
+
+ // delete characters from nStart to nStart + nLen
+ wxString& erase(size_type pos = 0, size_type n = npos)
+ {
+ wxSTRING_INVALIDATE_CACHE();
+
+ size_t from, len;
+ PosLenToImpl(pos, n, &from, &len);
+ m_impl.erase(from, len);
+
+ return *this;
+ }
+
+ // delete characters from first up to last
+ iterator erase(iterator first, iterator last)
+ {
+ wxSTRING_INVALIDATE_CACHE();
+
+ return iterator(this, m_impl.erase(first.impl(), last.impl()));
+ }
+
+ iterator erase(iterator first)
+ {
+ wxSTRING_UPDATE_CACHED_LENGTH(-1);
+
+ return iterator(this, m_impl.erase(first.impl()));
+ }
+
+#ifdef wxSTRING_BASE_HASNT_CLEAR
+ void clear() { erase(); }
+#else
+ void clear()
+ {
+ wxSTRING_SET_CACHED_LENGTH(0);
+
+ m_impl.clear();
+ }
+#endif
+
+ // replaces the substring of length nLen starting at nStart
+ wxString& replace(size_t nStart, size_t nLen, const char* sz)
+ {
+ wxSTRING_INVALIDATE_CACHE();
+
+ size_t from, len;
+ PosLenToImpl(nStart, nLen, &from, &len);
+ m_impl.replace(from, len, ImplStr(sz));
+
+ return *this;
+ }
+
+ wxString& replace(size_t nStart, size_t nLen, const wchar_t* sz)
+ {
+ wxSTRING_INVALIDATE_CACHE();
+
+ size_t from, len;
+ PosLenToImpl(nStart, nLen, &from, &len);
+ m_impl.replace(from, len, ImplStr(sz));
+
+ return *this;
+ }
+
+ // replaces the substring of length nLen starting at nStart
+ wxString& replace(size_t nStart, size_t nLen, const wxString& str)
+ {
+ wxSTRING_INVALIDATE_CACHE();
+
+ size_t from, len;
+ PosLenToImpl(nStart, nLen, &from, &len);
+ m_impl.replace(from, len, str.m_impl);
+
+ return *this;
+ }
+
+ // replaces the substring with nCount copies of ch
+ wxString& replace(size_t nStart, size_t nLen, size_t nCount, wxUniChar ch)
+ {
+ wxSTRING_INVALIDATE_CACHE();
+
+ size_t from, len;
+ PosLenToImpl(nStart, nLen, &from, &len);
+#if wxUSE_UNICODE_UTF8
+ if ( !ch.IsAscii() )
+ m_impl.replace(from, len, wxStringOperations::EncodeNChars(nCount, ch));
+ else
+#endif
+ m_impl.replace(from, len, nCount, (wxStringCharType)ch);
+
+ return *this;
+ }
+
+ // replaces a substring with another substring
+ wxString& replace(size_t nStart, size_t nLen,
+ const wxString& str, size_t nStart2, size_t nLen2)
+ {
+ wxSTRING_INVALIDATE_CACHE();
+
+ size_t from, len;
+ PosLenToImpl(nStart, nLen, &from, &len);
+
+ size_t from2, len2;
+ str.PosLenToImpl(nStart2, nLen2, &from2, &len2);
+
+ m_impl.replace(from, len, str.m_impl, from2, len2);
+
+ return *this;
+ }
+
+ // replaces the substring with first nCount chars of sz
+ wxString& replace(size_t nStart, size_t nLen,
+ const char* sz, size_t nCount)
+ {
+ wxSTRING_INVALIDATE_CACHE();
+
+ size_t from, len;
+ PosLenToImpl(nStart, nLen, &from, &len);
+
+ SubstrBufFromMB str(ImplStr(sz, nCount));
+
+ m_impl.replace(from, len, str.data, str.len);
+
+ return *this;
+ }
+
+ wxString& replace(size_t nStart, size_t nLen,
+ const wchar_t* sz, size_t nCount)
+ {
+ wxSTRING_INVALIDATE_CACHE();
+
+ size_t from, len;
+ PosLenToImpl(nStart, nLen, &from, &len);
+
+ SubstrBufFromWC str(ImplStr(sz, nCount));
+
+ m_impl.replace(from, len, str.data, str.len);
+
+ return *this;
+ }
+
+ wxString& replace(size_t nStart, size_t nLen,
+ const wxString& s, size_t nCount)
+ {
+ wxSTRING_INVALIDATE_CACHE();
+
+ size_t from, len;
+ PosLenToImpl(nStart, nLen, &from, &len);
+ m_impl.replace(from, len, s.m_impl.c_str(), s.LenToImpl(nCount));
+
+ return *this;
+ }
+
+ wxString& replace(iterator first, iterator last, const char* s)
+ {
+ wxSTRING_INVALIDATE_CACHE();
+
+ m_impl.replace(first.impl(), last.impl(), ImplStr(s));
+
+ return *this;
+ }
+
+ wxString& replace(iterator first, iterator last, const wchar_t* s)
+ {
+ wxSTRING_INVALIDATE_CACHE();
+
+ m_impl.replace(first.impl(), last.impl(), ImplStr(s));
+
+ return *this;
+ }
+
+ wxString& replace(iterator first, iterator last, const char* s, size_type n)
+ {
+ wxSTRING_INVALIDATE_CACHE();
+
+ SubstrBufFromMB str(ImplStr(s, n));
+ m_impl.replace(first.impl(), last.impl(), str.data, str.len);
+
+ return *this;
+ }
+
+ wxString& replace(iterator first, iterator last, const wchar_t* s, size_type n)
+ {
+ wxSTRING_INVALIDATE_CACHE();
+
+ SubstrBufFromWC str(ImplStr(s, n));
+ m_impl.replace(first.impl(), last.impl(), str.data, str.len);
+
+ return *this;
+ }
+
+ wxString& replace(iterator first, iterator last, const wxString& s)
+ {
+ wxSTRING_INVALIDATE_CACHE();
+
+ m_impl.replace(first.impl(), last.impl(), s.m_impl);
+
+ return *this;
+ }
+
+ wxString& replace(iterator first, iterator last, size_type n, wxUniChar ch)
+ {
+ wxSTRING_INVALIDATE_CACHE();
+
+#if wxUSE_UNICODE_UTF8
+ if ( !ch.IsAscii() )
+ m_impl.replace(first.impl(), last.impl(),
+ wxStringOperations::EncodeNChars(n, ch));
+ else
+#endif
+ m_impl.replace(first.impl(), last.impl(), n, (wxStringCharType)ch);
+
+ return *this;
+ }
+
+ wxString& replace(iterator first, iterator last,
+ const_iterator first1, const_iterator last1)
+ {
+ wxSTRING_INVALIDATE_CACHE();
+
+ m_impl.replace(first.impl(), last.impl(), first1.impl(), last1.impl());
+
+ return *this;
+ }
+
+ wxString& replace(iterator first, iterator last,
+ const char *first1, const char *last1)
+ { replace(first, last, first1, last1 - first1); return *this; }
+ wxString& replace(iterator first, iterator last,
+ const wchar_t *first1, const wchar_t *last1)
+ { replace(first, last, first1, last1 - first1); return *this; }
+
+ // swap two strings
+ void swap(wxString& str)
+ {
+#if wxUSE_STRING_POS_CACHE
+ // we modify not only this string but also the other one directly so we
+ // need to invalidate cache for both of them (we could also try to
+ // exchange their cache entries but it seems unlikely to be worth it)
+ InvalidateCache();
+ str.InvalidateCache();
+#endif // wxUSE_STRING_POS_CACHE
+
+ m_impl.swap(str.m_impl);
+ }
+
+ // find a substring
+ size_t find(const wxString& str, size_t nStart = 0) const
+ { return PosFromImpl(m_impl.find(str.m_impl, PosToImpl(nStart))); }
+
+ // find first n characters of sz
+ size_t find(const char* sz, size_t nStart = 0, size_t n = npos) const
+ {
+ SubstrBufFromMB str(ImplStr(sz, n));
+ return PosFromImpl(m_impl.find(str.data, PosToImpl(nStart), str.len));
+ }
+ size_t find(const wchar_t* sz, size_t nStart = 0, size_t n = npos) const
+ {
+ SubstrBufFromWC str(ImplStr(sz, n));
+ return PosFromImpl(m_impl.find(str.data, PosToImpl(nStart), str.len));
+ }
+ size_t find(const wxScopedCharBuffer& s, size_t nStart = 0, size_t n = npos) const
+ { return find(s.data(), nStart, n); }
+ size_t find(const wxScopedWCharBuffer& s, size_t nStart = 0, size_t n = npos) const
+ { return find(s.data(), nStart, n); }
+ size_t find(const wxCStrData& s, size_t nStart = 0, size_t n = npos) const
+ { return find(s.AsWChar(), nStart, n); }
+
+ // find the first occurrence of character ch after nStart
+ size_t find(wxUniChar ch, size_t nStart = 0) const
+ {
+#if wxUSE_UNICODE_UTF8
+ if ( !ch.IsAscii() )
+ return PosFromImpl(m_impl.find(wxStringOperations::EncodeChar(ch),
+ PosToImpl(nStart)));
+ else
+#endif
+ return PosFromImpl(m_impl.find((wxStringCharType)ch,
+ PosToImpl(nStart)));
+
+ }
+ size_t find(wxUniCharRef ch, size_t nStart = 0) const
+ { return find(wxUniChar(ch), nStart); }
+ size_t find(char ch, size_t nStart = 0) const
+ { return find(wxUniChar(ch), nStart); }
+ size_t find(unsigned char ch, size_t nStart = 0) const
+ { return find(wxUniChar(ch), nStart); }
+ size_t find(wchar_t ch, size_t nStart = 0) const
+ { return find(wxUniChar(ch), nStart); }
+
+ // rfind() family is exactly like find() but works right to left
+
+ // as find, but from the end
+ size_t rfind(const wxString& str, size_t nStart = npos) const
+ { return PosFromImpl(m_impl.rfind(str.m_impl, PosToImpl(nStart))); }
+
+ // as find, but from the end
+ size_t rfind(const char* sz, size_t nStart = npos, size_t n = npos) const
+ {
+ SubstrBufFromMB str(ImplStr(sz, n));
+ return PosFromImpl(m_impl.rfind(str.data, PosToImpl(nStart), str.len));
+ }
+ size_t rfind(const wchar_t* sz, size_t nStart = npos, size_t n = npos) const
+ {
+ SubstrBufFromWC str(ImplStr(sz, n));
+ return PosFromImpl(m_impl.rfind(str.data, PosToImpl(nStart), str.len));
+ }
+ size_t rfind(const wxScopedCharBuffer& s, size_t nStart = npos, size_t n = npos) const
+ { return rfind(s.data(), nStart, n); }
+ size_t rfind(const wxScopedWCharBuffer& s, size_t nStart = npos, size_t n = npos) const
+ { return rfind(s.data(), nStart, n); }
+ size_t rfind(const wxCStrData& s, size_t nStart = npos, size_t n = npos) const
+ { return rfind(s.AsWChar(), nStart, n); }
+ // as find, but from the end
+ size_t rfind(wxUniChar ch, size_t nStart = npos) const
+ {
+#if wxUSE_UNICODE_UTF8
+ if ( !ch.IsAscii() )
+ return PosFromImpl(m_impl.rfind(wxStringOperations::EncodeChar(ch),
+ PosToImpl(nStart)));
+ else
+#endif
+ return PosFromImpl(m_impl.rfind((wxStringCharType)ch,
+ PosToImpl(nStart)));
+ }
+ size_t rfind(wxUniCharRef ch, size_t nStart = npos) const
+ { return rfind(wxUniChar(ch), nStart); }
+ size_t rfind(char ch, size_t nStart = npos) const
+ { return rfind(wxUniChar(ch), nStart); }
+ size_t rfind(unsigned char ch, size_t nStart = npos) const
+ { return rfind(wxUniChar(ch), nStart); }
+ size_t rfind(wchar_t ch, size_t nStart = npos) const
+ { return rfind(wxUniChar(ch), nStart); }
+
+ // find first/last occurrence of any character (not) in the set:
+#if wxUSE_STL_BASED_WXSTRING && !wxUSE_UNICODE_UTF8
+ // FIXME-UTF8: this is not entirely correct, because it doesn't work if
+ // sizeof(wchar_t)==2 and surrogates are present in the string;
+ // should we care? Probably not.
+ size_t find_first_of(const wxString& str, size_t nStart = 0) const
+ { return m_impl.find_first_of(str.m_impl, nStart); }
+ size_t find_first_of(const char* sz, size_t nStart = 0) const
+ { return m_impl.find_first_of(ImplStr(sz), nStart); }
+ size_t find_first_of(const wchar_t* sz, size_t nStart = 0) const
+ { return m_impl.find_first_of(ImplStr(sz), nStart); }
+ size_t find_first_of(const char* sz, size_t nStart, size_t n) const
+ { return m_impl.find_first_of(ImplStr(sz), nStart, n); }
+ size_t find_first_of(const wchar_t* sz, size_t nStart, size_t n) const
+ { return m_impl.find_first_of(ImplStr(sz), nStart, n); }
+ size_t find_first_of(wxUniChar c, size_t nStart = 0) const
+ { return m_impl.find_first_of((wxChar)c, nStart); }
+
+ size_t find_last_of(const wxString& str, size_t nStart = npos) const
+ { return m_impl.find_last_of(str.m_impl, nStart); }
+ size_t find_last_of(const char* sz, size_t nStart = npos) const
+ { return m_impl.find_last_of(ImplStr(sz), nStart); }
+ size_t find_last_of(const wchar_t* sz, size_t nStart = npos) const
+ { return m_impl.find_last_of(ImplStr(sz), nStart); }
+ size_t find_last_of(const char* sz, size_t nStart, size_t n) const
+ { return m_impl.find_last_of(ImplStr(sz), nStart, n); }
+ size_t find_last_of(const wchar_t* sz, size_t nStart, size_t n) const
+ { return m_impl.find_last_of(ImplStr(sz), nStart, n); }
+ size_t find_last_of(wxUniChar c, size_t nStart = npos) const
+ { return m_impl.find_last_of((wxChar)c, nStart); }
+
+ size_t find_first_not_of(const wxString& str, size_t nStart = 0) const
+ { return m_impl.find_first_not_of(str.m_impl, nStart); }
+ size_t find_first_not_of(const char* sz, size_t nStart = 0) const
+ { return m_impl.find_first_not_of(ImplStr(sz), nStart); }
+ size_t find_first_not_of(const wchar_t* sz, size_t nStart = 0) const
+ { return m_impl.find_first_not_of(ImplStr(sz), nStart); }
+ size_t find_first_not_of(const char* sz, size_t nStart, size_t n) const
+ { return m_impl.find_first_not_of(ImplStr(sz), nStart, n); }
+ size_t find_first_not_of(const wchar_t* sz, size_t nStart, size_t n) const
+ { return m_impl.find_first_not_of(ImplStr(sz), nStart, n); }
+ size_t find_first_not_of(wxUniChar c, size_t nStart = 0) const
+ { return m_impl.find_first_not_of((wxChar)c, nStart); }
+
+ size_t find_last_not_of(const wxString& str, size_t nStart = npos) const
+ { return m_impl.find_last_not_of(str.m_impl, nStart); }
+ size_t find_last_not_of(const char* sz, size_t nStart = npos) const
+ { return m_impl.find_last_not_of(ImplStr(sz), nStart); }
+ size_t find_last_not_of(const wchar_t* sz, size_t nStart = npos) const
+ { return m_impl.find_last_not_of(ImplStr(sz), nStart); }
+ size_t find_last_not_of(const char* sz, size_t nStart, size_t n) const
+ { return m_impl.find_last_not_of(ImplStr(sz), nStart, n); }
+ size_t find_last_not_of(const wchar_t* sz, size_t nStart, size_t n) const
+ { return m_impl.find_last_not_of(ImplStr(sz), nStart, n); }
+ size_t find_last_not_of(wxUniChar c, size_t nStart = npos) const
+ { return m_impl.find_last_not_of((wxChar)c, nStart); }
+#else
+ // we can't use std::string implementation in UTF-8 build, because the
+ // character sets would be interpreted wrongly:
+
+ // as strpbrk() but starts at nStart, returns npos if not found
+ size_t find_first_of(const wxString& str, size_t nStart = 0) const
+#if wxUSE_UNICODE // FIXME-UTF8: temporary
+ { return find_first_of(str.wc_str(), nStart); }
+#else
+ { return find_first_of(str.mb_str(), nStart); }
+#endif
+ // same as above
+ size_t find_first_of(const char* sz, size_t nStart = 0) const;
+ size_t find_first_of(const wchar_t* sz, size_t nStart = 0) const;
+ size_t find_first_of(const char* sz, size_t nStart, size_t n) const;
+ size_t find_first_of(const wchar_t* sz, size_t nStart, size_t n) const;
+ // same as find(char, size_t)
+ size_t find_first_of(wxUniChar c, size_t nStart = 0) const
+ { return find(c, nStart); }
+ // find the last (starting from nStart) char from str in this string
+ size_t find_last_of (const wxString& str, size_t nStart = npos) const
+#if wxUSE_UNICODE // FIXME-UTF8: temporary
+ { return find_last_of(str.wc_str(), nStart); }
+#else
+ { return find_last_of(str.mb_str(), nStart); }
+#endif
+ // same as above
+ size_t find_last_of (const char* sz, size_t nStart = npos) const;
+ size_t find_last_of (const wchar_t* sz, size_t nStart = npos) const;
+ size_t find_last_of(const char* sz, size_t nStart, size_t n) const;
+ size_t find_last_of(const wchar_t* sz, size_t nStart, size_t n) const;
+ // same as above
+ size_t find_last_of(wxUniChar c, size_t nStart = npos) const
+ { return rfind(c, nStart); }
+
+ // find first/last occurrence of any character not in the set
+
+ // as strspn() (starting from nStart), returns npos on failure
+ size_t find_first_not_of(const wxString& str, size_t nStart = 0) const
+#if wxUSE_UNICODE // FIXME-UTF8: temporary
+ { return find_first_not_of(str.wc_str(), nStart); }
+#else
+ { return find_first_not_of(str.mb_str(), nStart); }
+#endif
+ // same as above
+ size_t find_first_not_of(const char* sz, size_t nStart = 0) const;
+ size_t find_first_not_of(const wchar_t* sz, size_t nStart = 0) const;
+ size_t find_first_not_of(const char* sz, size_t nStart, size_t n) const;
+ size_t find_first_not_of(const wchar_t* sz, size_t nStart, size_t n) const;
+ // same as above
+ size_t find_first_not_of(wxUniChar ch, size_t nStart = 0) const;
+ // as strcspn()
+ size_t find_last_not_of(const wxString& str, size_t nStart = npos) const
+#if wxUSE_UNICODE // FIXME-UTF8: temporary
+ { return find_last_not_of(str.wc_str(), nStart); }
+#else
+ { return find_last_not_of(str.mb_str(), nStart); }
+#endif
+ // same as above
+ size_t find_last_not_of(const char* sz, size_t nStart = npos) const;
+ size_t find_last_not_of(const wchar_t* sz, size_t nStart = npos) const;
+ size_t find_last_not_of(const char* sz, size_t nStart, size_t n) const;
+ size_t find_last_not_of(const wchar_t* sz, size_t nStart, size_t n) const;
+ // same as above
+ size_t find_last_not_of(wxUniChar ch, size_t nStart = npos) const;
+#endif // wxUSE_STL_BASED_WXSTRING && !wxUSE_UNICODE_UTF8 or not
+
+ // provide char/wchar_t/wxUniCharRef overloads for char-finding functions
+ // above to resolve ambiguities:
+ size_t find_first_of(wxUniCharRef ch, size_t nStart = 0) const
+ { return find_first_of(wxUniChar(ch), nStart); }
+ size_t find_first_of(char ch, size_t nStart = 0) const
+ { return find_first_of(wxUniChar(ch), nStart); }
+ size_t find_first_of(unsigned char ch, size_t nStart = 0) const
+ { return find_first_of(wxUniChar(ch), nStart); }
+ size_t find_first_of(wchar_t ch, size_t nStart = 0) const
+ { return find_first_of(wxUniChar(ch), nStart); }
+ size_t find_last_of(wxUniCharRef ch, size_t nStart = npos) const
+ { return find_last_of(wxUniChar(ch), nStart); }
+ size_t find_last_of(char ch, size_t nStart = npos) const
+ { return find_last_of(wxUniChar(ch), nStart); }
+ size_t find_last_of(unsigned char ch, size_t nStart = npos) const
+ { return find_last_of(wxUniChar(ch), nStart); }
+ size_t find_last_of(wchar_t ch, size_t nStart = npos) const
+ { return find_last_of(wxUniChar(ch), nStart); }
+ size_t find_first_not_of(wxUniCharRef ch, size_t nStart = 0) const
+ { return find_first_not_of(wxUniChar(ch), nStart); }
+ size_t find_first_not_of(char ch, size_t nStart = 0) const
+ { return find_first_not_of(wxUniChar(ch), nStart); }
+ size_t find_first_not_of(unsigned char ch, size_t nStart = 0) const
+ { return find_first_not_of(wxUniChar(ch), nStart); }
+ size_t find_first_not_of(wchar_t ch, size_t nStart = 0) const
+ { return find_first_not_of(wxUniChar(ch), nStart); }
+ size_t find_last_not_of(wxUniCharRef ch, size_t nStart = npos) const
+ { return find_last_not_of(wxUniChar(ch), nStart); }
+ size_t find_last_not_of(char ch, size_t nStart = npos) const
+ { return find_last_not_of(wxUniChar(ch), nStart); }
+ size_t find_last_not_of(unsigned char ch, size_t nStart = npos) const
+ { return find_last_not_of(wxUniChar(ch), nStart); }
+ size_t find_last_not_of(wchar_t ch, size_t nStart = npos) const
+ { return find_last_not_of(wxUniChar(ch), nStart); }
+
+ // and additional overloads for the versions taking strings:
+ size_t find_first_of(const wxCStrData& sz, size_t nStart = 0) const
+ { return find_first_of(sz.AsString(), nStart); }
+ size_t find_first_of(const wxScopedCharBuffer& sz, size_t nStart = 0) const
+ { return find_first_of(sz.data(), nStart); }
+ size_t find_first_of(const wxScopedWCharBuffer& sz, size_t nStart = 0) const
+ { return find_first_of(sz.data(), nStart); }
+ size_t find_first_of(const wxCStrData& sz, size_t nStart, size_t n) const
+ { return find_first_of(sz.AsWChar(), nStart, n); }
+ size_t find_first_of(const wxScopedCharBuffer& sz, size_t nStart, size_t n) const
+ { return find_first_of(sz.data(), nStart, n); }
+ size_t find_first_of(const wxScopedWCharBuffer& sz, size_t nStart, size_t n) const
+ { return find_first_of(sz.data(), nStart, n); }
+
+ size_t find_last_of(const wxCStrData& sz, size_t nStart = 0) const
+ { return find_last_of(sz.AsString(), nStart); }
+ size_t find_last_of(const wxScopedCharBuffer& sz, size_t nStart = 0) const
+ { return find_last_of(sz.data(), nStart); }
+ size_t find_last_of(const wxScopedWCharBuffer& sz, size_t nStart = 0) const
+ { return find_last_of(sz.data(), nStart); }
+ size_t find_last_of(const wxCStrData& sz, size_t nStart, size_t n) const
+ { return find_last_of(sz.AsWChar(), nStart, n); }
+ size_t find_last_of(const wxScopedCharBuffer& sz, size_t nStart, size_t n) const
+ { return find_last_of(sz.data(), nStart, n); }
+ size_t find_last_of(const wxScopedWCharBuffer& sz, size_t nStart, size_t n) const
+ { return find_last_of(sz.data(), nStart, n); }
+
+ size_t find_first_not_of(const wxCStrData& sz, size_t nStart = 0) const
+ { return find_first_not_of(sz.AsString(), nStart); }
+ size_t find_first_not_of(const wxScopedCharBuffer& sz, size_t nStart = 0) const
+ { return find_first_not_of(sz.data(), nStart); }
+ size_t find_first_not_of(const wxScopedWCharBuffer& sz, size_t nStart = 0) const
+ { return find_first_not_of(sz.data(), nStart); }
+ size_t find_first_not_of(const wxCStrData& sz, size_t nStart, size_t n) const
+ { return find_first_not_of(sz.AsWChar(), nStart, n); }
+ size_t find_first_not_of(const wxScopedCharBuffer& sz, size_t nStart, size_t n) const
+ { return find_first_not_of(sz.data(), nStart, n); }
+ size_t find_first_not_of(const wxScopedWCharBuffer& sz, size_t nStart, size_t n) const
+ { return find_first_not_of(sz.data(), nStart, n); }
+
+ size_t find_last_not_of(const wxCStrData& sz, size_t nStart = 0) const
+ { return find_last_not_of(sz.AsString(), nStart); }
+ size_t find_last_not_of(const wxScopedCharBuffer& sz, size_t nStart = 0) const
+ { return find_last_not_of(sz.data(), nStart); }
+ size_t find_last_not_of(const wxScopedWCharBuffer& sz, size_t nStart = 0) const
+ { return find_last_not_of(sz.data(), nStart); }
+ size_t find_last_not_of(const wxCStrData& sz, size_t nStart, size_t n) const
+ { return find_last_not_of(sz.AsWChar(), nStart, n); }
+ size_t find_last_not_of(const wxScopedCharBuffer& sz, size_t nStart, size_t n) const
+ { return find_last_not_of(sz.data(), nStart, n); }
+ size_t find_last_not_of(const wxScopedWCharBuffer& sz, size_t nStart, size_t n) const
+ { return find_last_not_of(sz.data(), nStart, n); }
+
+ // string += string
+ wxString& operator+=(const wxString& s)
+ {
+ wxSTRING_INVALIDATE_CACHED_LENGTH();
+
+ m_impl += s.m_impl;
+ return *this;
+ }
+ // string += C string
+ wxString& operator+=(const char *psz)
+ {
+ wxSTRING_INVALIDATE_CACHED_LENGTH();
+
+ m_impl += ImplStr(psz);
+ return *this;
+ }
+ wxString& operator+=(const wchar_t *pwz)
+ {
+ wxSTRING_INVALIDATE_CACHED_LENGTH();
+
+ m_impl += ImplStr(pwz);
+ return *this;
+ }
+ wxString& operator+=(const wxCStrData& s)
+ {
+ wxSTRING_INVALIDATE_CACHED_LENGTH();
+
+ m_impl += s.AsString().m_impl;
+ return *this;
+ }
+ wxString& operator+=(const wxScopedCharBuffer& s)
+ { return append(s); }
+ wxString& operator+=(const wxScopedWCharBuffer& s)
+ { return append(s); }
+ // string += char
+ wxString& operator+=(wxUniChar ch)
+ {
+ wxSTRING_UPDATE_CACHED_LENGTH(1);
+
+#if wxUSE_UNICODE_UTF8
+ if ( !ch.IsAscii() )
+ m_impl += wxStringOperations::EncodeChar(ch);
+ else
+#endif
+ m_impl += (wxStringCharType)ch;
+ return *this;
+ }
+ wxString& operator+=(wxUniCharRef ch) { return *this += wxUniChar(ch); }
+ wxString& operator+=(int ch) { return *this += wxUniChar(ch); }
+ wxString& operator+=(char ch) { return *this += wxUniChar(ch); }
+ wxString& operator+=(unsigned char ch) { return *this += wxUniChar(ch); }
+ wxString& operator+=(wchar_t ch) { return *this += wxUniChar(ch); }
+
+private:
+#if !wxUSE_STL_BASED_WXSTRING
+ // helpers for wxStringBuffer and wxStringBufferLength
+ wxStringCharType *DoGetWriteBuf(size_t nLen)
+ {
+ return m_impl.DoGetWriteBuf(nLen);
+ }
+
+ void DoUngetWriteBuf()
+ {
+ wxSTRING_INVALIDATE_CACHE();
+
+ m_impl.DoUngetWriteBuf();
+ }
+
+ void DoUngetWriteBuf(size_t nLen)
+ {
+ wxSTRING_SET_CACHED_LENGTH(nLen);
+
+ m_impl.DoUngetWriteBuf(nLen);
+ }
+#endif // !wxUSE_STL_BASED_WXSTRING
+
+#ifndef wxNEEDS_WXSTRING_PRINTF_MIXIN
+ #if !wxUSE_UTF8_LOCALE_ONLY
+ int DoPrintfWchar(const wxChar *format, ...);
+ static wxString DoFormatWchar(const wxChar *format, ...);
+ #endif
+ #if wxUSE_UNICODE_UTF8
+ int DoPrintfUtf8(const char *format, ...);
+ static wxString DoFormatUtf8(const char *format, ...);
+ #endif
+#endif
+
+#if !wxUSE_STL_BASED_WXSTRING
+ // check string's data validity
+ bool IsValid() const { return m_impl.GetStringData()->IsValid(); }
+#endif
+
+private:
+ wxStringImpl m_impl;
+
+ // buffers for compatibility conversion from (char*)c_str() and
+ // (wchar_t*)c_str(): the pointers returned by these functions should remain
+ // valid until the string itself is modified for compatibility with the
+ // existing code and consistency with std::string::c_str() so returning a
+ // temporary buffer won't do and we need to cache the conversion results
+
+ // TODO-UTF8: benchmark various approaches to keeping compatibility buffers
+ template<typename T>
+ struct ConvertedBuffer
+ {
+ // notice that there is no need to initialize m_len here as it's unused
+ // as long as m_str is NULL
+ ConvertedBuffer() : m_str(NULL) {}
+ ~ConvertedBuffer()
+ { free(m_str); }
+
+ bool Extend(size_t len)
+ {
+ // add extra 1 for the trailing NUL
+ void * const str = realloc(m_str, sizeof(T)*(len + 1));
+ if ( !str )
+ return false;
+
+ m_str = static_cast<T *>(str);
+ m_len = len;
+
+ return true;
+ }
+
+ const wxScopedCharTypeBuffer<T> AsScopedBuffer() const
+ {
+ return wxScopedCharTypeBuffer<T>::CreateNonOwned(m_str, m_len);
+ }
+
+ T *m_str; // pointer to the string data
+ size_t m_len; // length, not size, i.e. in chars and without last NUL
+ };
+
+
+#if wxUSE_UNICODE
+ // common mb_str() and wxCStrData::AsChar() helper: performs the conversion
+ // and returns either m_convertedToChar.m_str (in which case its m_len is
+ // also updated) or NULL if it failed
+ //
+ // there is an important exception: in wxUSE_UNICODE_UTF8 build if conv is a
+ // UTF-8 one, we return m_impl.c_str() directly, without doing any conversion
+ // as optimization and so the caller needs to check for this before using
+ // m_convertedToChar
+ //
+ // NB: AsChar() returns char* in any build, unlike mb_str()
+ const char *AsChar(const wxMBConv& conv) const;
+
+ // mb_str() implementation helper
+ wxScopedCharBuffer AsCharBuf(const wxMBConv& conv) const
+ {
+#if wxUSE_UNICODE_UTF8
+ // avoid conversion if we can
+ if ( conv.IsUTF8() )
+ {
+ return wxScopedCharBuffer::CreateNonOwned(m_impl.c_str(),
+ m_impl.length());
+ }
+#endif // wxUSE_UNICODE_UTF8
+
+ // call this solely in order to fill in m_convertedToChar as AsChar()
+ // updates it as a side effect: this is a bit ugly but it's a completely
+ // internal function so the users of this class shouldn't care or know
+ // about it and doing it like this, i.e. having a separate AsChar(),
+ // allows us to avoid the creation and destruction of a temporary buffer
+ // when using wxCStrData without duplicating any code
+ if ( !AsChar(conv) )
+ {
+ // although it would be probably more correct to return NULL buffer
+ // from here if the conversion fails, a lot of existing code doesn't
+ // expect mb_str() (or wc_str()) to ever return NULL so return an
+ // empty string otherwise to avoid crashes in it
+ //
+ // also, some existing code does check for the conversion success and
+ // so asserting here would be bad too -- even if it does mean that
+ // silently losing data is possible for badly written code
+ return wxScopedCharBuffer::CreateNonOwned("", 0);
+ }
+
+ return m_convertedToChar.AsScopedBuffer();
+ }
+
+ ConvertedBuffer<char> m_convertedToChar;
+#endif // !wxUSE_UNICODE
+
+#if !wxUSE_UNICODE_WCHAR
+ // common wc_str() and wxCStrData::AsWChar() helper for both UTF-8 and ANSI
+ // builds: converts the string contents into m_convertedToWChar and returns
+ // NULL if the conversion failed (this can only happen in ANSI build)
+ //
+ // NB: AsWChar() returns wchar_t* in any build, unlike wc_str()
+ const wchar_t *AsWChar(const wxMBConv& conv) const;
+
+ // wc_str() implementation helper
+ wxScopedWCharBuffer AsWCharBuf(const wxMBConv& conv) const
+ {
+ if ( !AsWChar(conv) )
+ return wxScopedWCharBuffer::CreateNonOwned(L"", 0);
+
+ return m_convertedToWChar.AsScopedBuffer();
+ }