+ // copy ctor
+ wxString(const wxString& stringSrc) : m_impl(stringSrc.m_impl) { }
+
+ // string containing nRepeat copies of ch
+ wxString(wxUniChar ch, size_t nRepeat = 1 )
+ { assign(nRepeat, ch); }
+ wxString(size_t nRepeat, wxUniChar ch)
+ { assign(nRepeat, ch); }
+ wxString(wxUniCharRef ch, size_t nRepeat = 1)
+ { assign(nRepeat, ch); }
+ wxString(size_t nRepeat, wxUniCharRef ch)
+ { assign(nRepeat, ch); }
+ wxString(char ch, size_t nRepeat = 1)
+ { assign(nRepeat, ch); }
+ wxString(size_t nRepeat, char ch)
+ { assign(nRepeat, ch); }
+ wxString(wchar_t ch, size_t nRepeat = 1)
+ { assign(nRepeat, ch); }
+ wxString(size_t nRepeat, wchar_t ch)
+ { assign(nRepeat, ch); }
+
+ // ctors from char* strings:
+ wxString(const char *psz)
+ : m_impl(ImplStr(psz)) {}
+ wxString(const char *psz, const wxMBConv& conv)
+ : m_impl(ImplStr(psz, conv)) {}
+ wxString(const char *psz, size_t nLength)
+ { assign(psz, nLength); }
+ wxString(const char *psz, const wxMBConv& conv, size_t nLength)
+ {
+ SubstrBufFromMB str(ImplStr(psz, nLength, conv));
+ m_impl.assign(str.data, str.len);
+ }
+
+ // and unsigned char*:
+ wxString(const unsigned char *psz)
+ : m_impl(ImplStr((const char*)psz)) {}
+ wxString(const unsigned char *psz, const wxMBConv& conv)
+ : m_impl(ImplStr((const char*)psz, conv)) {}
+ wxString(const unsigned char *psz, size_t nLength)
+ { assign((const char*)psz, nLength); }
+ wxString(const unsigned char *psz, const wxMBConv& conv, size_t nLength)
+ {
+ SubstrBufFromMB str(ImplStr((const char*)psz, nLength, conv));
+ m_impl.assign(str.data, str.len);
+ }
+
+ // ctors from wchar_t* strings:
+ wxString(const wchar_t *pwz)
+ : m_impl(ImplStr(pwz)) {}
+ wxString(const wchar_t *pwz, const wxMBConv& WXUNUSED(conv))
+ : m_impl(ImplStr(pwz)) {}
+ wxString(const wchar_t *pwz, size_t nLength)
+ { assign(pwz, nLength); }
+ wxString(const wchar_t *pwz, const wxMBConv& WXUNUSED(conv), size_t nLength)
+ { assign(pwz, nLength); }
+
+ wxString(const wxScopedCharBuffer& buf)
+ { assign(buf.data(), buf.length()); }
+ wxString(const wxScopedWCharBuffer& buf)
+ { assign(buf.data(), buf.length()); }
+
+ // NB: this version uses m_impl.c_str() to force making a copy of the
+ // string, so that "wxString(str.c_str())" idiom for passing strings
+ // between threads works
+ wxString(const wxCStrData& cstr)
+ : m_impl(cstr.AsString().m_impl.c_str()) { }
+
+ // as we provide both ctors with this signature for both char and unsigned
+ // char string, we need to provide one for wxCStrData to resolve ambiguity
+ wxString(const wxCStrData& cstr, size_t nLength)
+ : m_impl(cstr.AsString().Mid(0, nLength).m_impl) {}
+
+ // and because wxString is convertible to wxCStrData and const wxChar *
+ // we also need to provide this one
+ wxString(const wxString& str, size_t nLength)
+ { assign(str, nLength); }
+
+
+#if wxUSE_STRING_POS_CACHE
+ ~wxString()
+ {
+ // we need to invalidate our cache entry as another string could be
+ // recreated at the same address (unlikely, but still possible, with the
+ // heap-allocated strings but perfectly common with stack-allocated ones)
+ InvalidateCache();
+ }
+#endif // wxUSE_STRING_POS_CACHE
+
+ // even if we're not built with wxUSE_STL == 1 it is very convenient to allow
+ // implicit conversions from std::string to wxString and vice verse as this
+ // allows to use the same strings in non-GUI and GUI code, however we don't
+ // want to unconditionally add this ctor as it would make wx lib dependent on
+ // libstdc++ on some Linux versions which is bad, so instead we ask the
+ // client code to define this wxUSE_STD_STRING symbol if they need it
+#if wxUSE_STD_STRING
+ #if wxUSE_UNICODE_WCHAR
+ wxString(const wxStdWideString& str) : m_impl(str) {}
+ #else // UTF-8 or ANSI
+ wxString(const wxStdWideString& str)
+ { assign(str.c_str(), str.length()); }
+ #endif
+
+ #if !wxUSE_UNICODE // ANSI build
+ // FIXME-UTF8: do this in UTF8 build #if wxUSE_UTF8_LOCALE_ONLY, too
+ wxString(const std::string& str) : m_impl(str) {}
+ #else // Unicode
+ wxString(const std::string& str)
+ { assign(str.c_str(), str.length()); }
+ #endif
+#endif // wxUSE_STD_STRING
+
+ // Unlike ctor from std::string, we provide conversion to std::string only
+ // if wxUSE_STL and not merely wxUSE_STD_STRING (which is on by default),
+ // because it conflicts with operator const char/wchar_t*:
+#if wxUSE_STL
+ #if wxUSE_UNICODE_WCHAR && wxUSE_STL_BASED_WXSTRING
+ // wxStringImpl is std::string in the encoding we want
+ operator const wxStdWideString&() const { return m_impl; }
+ #else
+ // wxStringImpl is either not std::string or needs conversion
+ operator wxStdWideString() const
+ {
+ wxScopedWCharBuffer buf(wc_str());
+ return wxStdWideString(buf.data(), buf.length());
+ }
+ #endif
+
+ #if (!wxUSE_UNICODE || wxUSE_UTF8_LOCALE_ONLY) && wxUSE_STL_BASED_WXSTRING
+ // wxStringImpl is std::string in the encoding we want
+ operator const std::string&() const { return m_impl; }
+ #else
+ // wxStringImpl is either not std::string or needs conversion
+ operator std::string() const
+ {
+ wxScopedCharBuffer buf(mb_str());
+ return std::string(buf.data(), buf.length());
+ }
+ #endif
+#endif // wxUSE_STL
+
+ wxString Clone() const
+ {
+ // make a deep copy of the string, i.e. the returned string will have
+ // ref count = 1 with refcounted implementation
+ return wxString::FromImpl(wxStringImpl(m_impl.c_str(), m_impl.length()));
+ }
+
+ // first valid index position
+ const_iterator begin() const { return const_iterator(this, m_impl.begin()); }
+ iterator begin() { return iterator(this, m_impl.begin()); }
+ // position one after the last valid one
+ const_iterator end() const { return const_iterator(this, m_impl.end()); }
+ iterator end() { return iterator(this, m_impl.end()); }
+
+ // first element of the reversed string
+ const_reverse_iterator rbegin() const
+ { return const_reverse_iterator(end()); }
+ reverse_iterator rbegin()
+ { return reverse_iterator(end()); }
+ // one beyond the end of the reversed string
+ const_reverse_iterator rend() const
+ { return const_reverse_iterator(begin()); }
+ reverse_iterator rend()
+ { return reverse_iterator(begin()); }
+
+ // std::string methods:
+#if wxUSE_UNICODE_UTF8
+ size_t length() const
+ {
+#if wxUSE_STRING_POS_CACHE
+ wxCACHE_PROFILE_FIELD_INC(lentot);
+
+ Cache::Element * const cache = GetCacheElement();
+
+ if ( cache->len == npos )
+ {
+ // it's probably not worth trying to be clever and using cache->pos
+ // here as it's probably 0 anyhow -- you usually call length() before
+ // starting to index the string
+ cache->len = end() - begin();
+ }
+ else
+ {
+ wxCACHE_PROFILE_FIELD_INC(lenhits);
+
+ wxSTRING_CACHE_ASSERT( (int)cache->len == end() - begin() );
+ }
+
+ return cache->len;
+#else // !wxUSE_STRING_POS_CACHE
+ return end() - begin();
+#endif // wxUSE_STRING_POS_CACHE/!wxUSE_STRING_POS_CACHE
+ }
+#else
+ size_t length() const { return m_impl.length(); }
+#endif
+
+ size_type size() const { return length(); }
+ size_type max_size() const { return npos; }
+
+ bool empty() const { return m_impl.empty(); }
+
+ // NB: these methods don't have a well-defined meaning in UTF-8 case
+ size_type capacity() const { return m_impl.capacity(); }
+ void reserve(size_t sz) { m_impl.reserve(sz); }
+
+ void resize(size_t nSize, wxUniChar ch = wxT('\0'))
+ {
+ const size_t len = length();
+ if ( nSize == len)
+ return;
+
+#if wxUSE_UNICODE_UTF8
+ if ( nSize < len )
+ {
+ wxSTRING_INVALIDATE_CACHE();
+
+ // we can't use wxStringImpl::resize() for truncating the string as it
+ // counts in bytes, not characters
+ erase(nSize);
+ return;
+ }
+
+ // we also can't use (presumably more efficient) resize() if we have to
+ // append characters taking more than one byte
+ if ( !ch.IsAscii() )
+ {
+ append(nSize - len, ch);
+ }
+ else // can use (presumably faster) resize() version
+#endif // wxUSE_UNICODE_UTF8
+ {
+ wxSTRING_INVALIDATE_CACHED_LENGTH();
+
+ m_impl.resize(nSize, (wxStringCharType)ch);
+ }
+ }
+
+ wxString substr(size_t nStart = 0, size_t nLen = npos) const
+ {
+ size_t pos, len;
+ PosLenToImpl(nStart, nLen, &pos, &len);
+ return FromImpl(m_impl.substr(pos, len));
+ }
+
+ // generic attributes & operations
+ // as standard strlen()
+ size_t Len() const { return length(); }
+ // string contains any characters?
+ bool IsEmpty() const { return empty(); }
+ // empty string is "false", so !str will return true
+ bool operator!() const { return empty(); }
+ // truncate the string to given length
+ wxString& Truncate(size_t uiLen);
+ // empty string contents
+ void Empty() { clear(); }
+ // empty the string and free memory
+ void Clear() { clear(); }
+
+ // contents test
+ // Is an ascii value
+ bool IsAscii() const;
+ // Is a number
+ bool IsNumber() const;
+ // Is a word
+ bool IsWord() const;
+
+ // data access (all indexes are 0 based)
+ // read access
+ wxUniChar at(size_t n) const
+ { return wxStringOperations::DecodeChar(m_impl.begin() + PosToImpl(n)); }
+ wxUniChar GetChar(size_t n) const
+ { return at(n); }
+ // read/write access
+ wxUniCharRef at(size_t n)
+ { return *GetIterForNthChar(n); }
+ wxUniCharRef GetWritableChar(size_t n)
+ { return at(n); }
+ // write access
+ void SetChar(size_t n, wxUniChar ch)
+ { at(n) = ch; }
+
+ // get last character
+ wxUniChar Last() const
+ {
+ wxASSERT_MSG( !empty(), _T("wxString: index out of bounds") );
+ return *rbegin();
+ }
+
+ // get writable last character
+ wxUniCharRef Last()
+ {
+ wxASSERT_MSG( !empty(), _T("wxString: index out of bounds") );
+ return *rbegin();
+ }
+
+ /*
+ Note that we we must define all of the overloads below to avoid
+ ambiguity when using str[0].
+ */
+ wxUniChar operator[](int n) const
+ { return at(n); }
+ wxUniChar operator[](long n) const
+ { return at(n); }
+ wxUniChar operator[](size_t n) const
+ { return at(n); }
+#ifndef wxSIZE_T_IS_UINT
+ wxUniChar operator[](unsigned int n) const
+ { return at(n); }
+#endif // size_t != unsigned int
+
+ // operator versions of GetWriteableChar()
+ wxUniCharRef operator[](int n)
+ { return at(n); }
+ wxUniCharRef operator[](long n)
+ { return at(n); }
+ wxUniCharRef operator[](size_t n)
+ { return at(n); }
+#ifndef wxSIZE_T_IS_UINT
+ wxUniCharRef operator[](unsigned int n)
+ { return at(n); }
+#endif // size_t != unsigned int
+
+
+ /*
+ Overview of wxString conversions, implicit and explicit:
+
+ - wxString has a std::[w]string-like c_str() method, however it does
+ not return a C-style string directly but instead returns wxCStrData
+ helper object which is convertible to either "char *" narrow string
+ or "wchar_t *" wide string. Usually the correct conversion will be
+ applied by the compiler automatically but if this doesn't happen you
+ need to explicitly choose one using wxCStrData::AsChar() or AsWChar()
+ methods or another wxString conversion function.
+
+ - One of the places where the conversion does *NOT* happen correctly is
+ when c_str() is passed to a vararg function such as printf() so you
+ must *NOT* use c_str() with them. Either use wxPrintf() (all wx
+ functions do handle c_str() correctly, even if they appear to be
+ vararg (but they're not, really)) or add an explicit AsChar() or, if
+ compatibility with previous wxWidgets versions is important, add a
+ cast to "const char *".
+
+ - In non-STL mode only, wxString is also implicitly convertible to
+ wxCStrData. The same warning as above applies.
+
+ - c_str() is polymorphic as it can be converted to either narrow or
+ wide string. If you explicitly need one or the other, choose to use
+ mb_str() (for narrow) or wc_str() (for wide) instead. Notice that
+ these functions can return either the pointer to string directly (if
+ this is what the string uses internally) or a temporary buffer
+ containing the string and convertible to it. Again, conversion will
+ usually be done automatically by the compiler but beware of the
+ vararg functions: you need an explicit cast when using them.
+
+ - There are also non-const versions of mb_str() and wc_str() called
+ char_str() and wchar_str(). They are only meant to be used with
+ non-const-correct functions and they always return buffers.
+
+ - Finally wx_str() returns whatever string representation is used by
+ wxString internally. It may be either a narrow or wide string
+ depending on wxWidgets build mode but it will always be a raw pointer
+ (and not a buffer).
+ */
+
+ // explicit conversion to wxCStrData
+ wxCStrData c_str() const { return wxCStrData(this); }
+ wxCStrData data() const { return c_str(); }
+
+ // implicit conversion to wxCStrData
+ operator wxCStrData() const { return c_str(); }
+
+ // the first two operators conflict with operators for conversion to
+ // std::string and they must be disabled in STL build; the next one only
+ // makes sense if conversions to char* are also defined and not defining it
+ // in STL build also helps us to get more clear error messages for the code
+ // which relies on implicit conversion to char* in STL build
+#if !wxUSE_STL
+ operator const char*() const { return c_str(); }
+ operator const wchar_t*() const { return c_str(); }
+
+ // implicit conversion to untyped pointer for compatibility with previous
+ // wxWidgets versions: this is the same as conversion to const char * so it
+ // may fail!
+ operator const void*() const { return c_str(); }
+#endif // wxUSE_STL
+
+ // identical to c_str(), for MFC compatibility
+ const wxCStrData GetData() const { return c_str(); }
+
+ // explicit conversion to C string in internal representation (char*,
+ // wchar_t*, UTF-8-encoded char*, depending on the build):
+ const wxStringCharType *wx_str() const { return m_impl.c_str(); }
+
+ // conversion to *non-const* multibyte or widestring buffer; modifying
+ // returned buffer won't affect the string, these methods are only useful
+ // for passing values to const-incorrect functions
+ wxWritableCharBuffer char_str(const wxMBConv& conv = wxConvLibc) const
+ { return mb_str(conv); }
+ wxWritableWCharBuffer wchar_str() const { return wc_str(); }
+
+ // conversion to the buffer of the given type T (= char or wchar_t) and
+ // also optionally return the buffer length
+ //
+ // this is mostly/only useful for the template functions
+ //
+ // FIXME-VC6: the second argument only exists for VC6 which doesn't support
+ // explicit template function selection, do not use it unless
+ // you must support VC6!
+ template <typename T>
+ wxCharTypeBuffer<T> tchar_str(size_t *len = NULL,
+ T * WXUNUSED(dummy) = NULL) const
+ {
+#if wxUSE_UNICODE
+ // we need a helper dispatcher depending on type
+ return wxPrivate::wxStringAsBufHelper<T>::Get(*this, len);
+#else // ANSI
+ // T can only be char in ANSI build
+ if ( len )
+ *len = length();
+
+ return wxCharTypeBuffer<T>::CreateNonOwned(wx_str(), length());
+#endif // Unicode build kind
+ }
+
+ // conversion to/from plain (i.e. 7 bit) ASCII: this is useful for
+ // converting numbers or strings which are certain not to contain special
+ // chars (typically system functions, X atoms, environment variables etc.)
+ //
+ // the behaviour of these functions with the strings containing anything
+ // else than 7 bit ASCII characters is undefined, use at your own risk.
+#if wxUSE_UNICODE
+ static wxString FromAscii(const char *ascii, size_t len);
+ static wxString FromAscii(const char *ascii);
+ static wxString FromAscii(char ascii);
+ const wxScopedCharBuffer ToAscii() const;
+#else // ANSI
+ static wxString FromAscii(const char *ascii) { return wxString( ascii ); }
+ static wxString FromAscii(const char *ascii, size_t len)
+ { return wxString( ascii, len ); }
+ static wxString FromAscii(char ascii) { return wxString( ascii ); }
+ const char *ToAscii() const { return c_str(); }
+#endif // Unicode/!Unicode
+
+ // also provide unsigned char overloads as signed/unsigned doesn't matter
+ // for 7 bit ASCII characters
+ static wxString FromAscii(const unsigned char *ascii)
+ { return FromAscii((const char *)ascii); }
+ static wxString FromAscii(const unsigned char *ascii, size_t len)
+ { return FromAscii((const char *)ascii, len); }
+
+ // conversion to/from UTF-8:
+#if wxUSE_UNICODE_UTF8
+ static wxString FromUTF8Unchecked(const char *utf8)
+ {
+ if ( !utf8 )
+ return wxEmptyString;
+
+ wxASSERT( wxStringOperations::IsValidUtf8String(utf8) );
+ return FromImpl(wxStringImpl(utf8));
+ }
+ static wxString FromUTF8Unchecked(const char *utf8, size_t len)
+ {
+ if ( !utf8 )
+ return wxEmptyString;
+ if ( len == npos )
+ return FromUTF8Unchecked(utf8);
+
+ wxASSERT( wxStringOperations::IsValidUtf8String(utf8, len) );
+ return FromImpl(wxStringImpl(utf8, len));
+ }
+
+ static wxString FromUTF8(const char *utf8)
+ {
+ if ( !utf8 || !wxStringOperations::IsValidUtf8String(utf8) )
+ return "";
+
+ return FromImpl(wxStringImpl(utf8));
+ }
+ static wxString FromUTF8(const char *utf8, size_t len)
+ {
+ if ( len == npos )
+ return FromUTF8(utf8);
+
+ if ( !utf8 || !wxStringOperations::IsValidUtf8String(utf8, len) )
+ return "";
+
+ return FromImpl(wxStringImpl(utf8, len));
+ }
+
+ const wxScopedCharBuffer utf8_str() const
+ { return wxCharBuffer::CreateNonOwned(m_impl.c_str(), m_impl.length()); }
+
+ // this function exists in UTF-8 build only and returns the length of the
+ // internal UTF-8 representation
+ size_t utf8_length() const { return m_impl.length(); }
+#elif wxUSE_UNICODE_WCHAR
+ static wxString FromUTF8(const char *utf8, size_t len = npos)
+ { return wxString(utf8, wxMBConvUTF8(), len); }
+ static wxString FromUTF8Unchecked(const char *utf8, size_t len = npos)
+ {
+ const wxString s(utf8, wxMBConvUTF8(), len);
+ wxASSERT_MSG( !utf8 || !*utf8 || !s.empty(),
+ "string must be valid UTF-8" );
+ return s;
+ }
+ const wxScopedCharBuffer utf8_str() const { return mb_str(wxMBConvUTF8()); }
+#else // ANSI
+ static wxString FromUTF8(const char *utf8)
+ { return wxString(wxMBConvUTF8().cMB2WC(utf8)); }
+ static wxString FromUTF8(const char *utf8, size_t len)
+ {
+ size_t wlen;
+ wxScopedWCharBuffer buf(wxMBConvUTF8().cMB2WC(utf8, len == npos ? wxNO_LEN : len, &wlen));
+ return wxString(buf.data(), wlen);
+ }
+ static wxString FromUTF8Unchecked(const char *utf8, size_t len = npos)
+ {
+ size_t wlen;
+ wxScopedWCharBuffer buf
+ (
+ wxMBConvUTF8().cMB2WC
+ (
+ utf8,
+ len == npos ? wxNO_LEN : len,
+ &wlen
+ )
+ );
+ wxASSERT_MSG( !utf8 || !*utf8 || wlen,
+ "string must be valid UTF-8" );
+
+ return wxString(buf.data(), wlen);
+ }
+ const wxScopedCharBuffer utf8_str() const
+ { return wxMBConvUTF8().cWC2MB(wc_str()); }
+#endif
+
+ const wxScopedCharBuffer ToUTF8() const { return utf8_str(); }
+
+ // functions for storing binary data in wxString:
+#if wxUSE_UNICODE
+ static wxString From8BitData(const char *data, size_t len)
+ { return wxString(data, wxConvISO8859_1, len); }
+ // version for NUL-terminated data:
+ static wxString From8BitData(const char *data)
+ { return wxString(data, wxConvISO8859_1); }
+ const wxScopedCharBuffer To8BitData() const
+ { return mb_str(wxConvISO8859_1); }
+#else // ANSI
+ static wxString From8BitData(const char *data, size_t len)
+ { return wxString(data, len); }
+ // version for NUL-terminated data:
+ static wxString From8BitData(const char *data)
+ { return wxString(data); }
+ const char *To8BitData() const { return c_str(); }
+#endif // Unicode/ANSI
+
+ // conversions with (possible) format conversions: have to return a
+ // buffer with temporary data
+ //
+ // the functions defined (in either Unicode or ANSI) mode are mb_str() to
+ // return an ANSI (multibyte) string, wc_str() to return a wide string and
+ // fn_str() to return a string which should be used with the OS APIs
+ // accepting the file names. The return value is always the same, but the
+ // type differs because a function may either return pointer to the buffer
+ // directly or have to use intermediate buffer for translation.
+
+#if wxUSE_UNICODE
+
+ // this is an optimization: even though using mb_str(wxConvLibc) does the
+ // same thing (i.e. returns pointer to internal representation as locale is
+ // always an UTF-8 one) in wxUSE_UTF8_LOCALE_ONLY case, we can avoid the
+ // extra checks and the temporary buffer construction by providing a
+ // separate mb_str() overload
+#if wxUSE_UTF8_LOCALE_ONLY
+ const char* mb_str() const { return wx_str(); }
+ const wxScopedCharBuffer mb_str(const wxMBConv& conv) const
+ {
+ return AsCharBuf(conv);
+ }
+#else // !wxUSE_UTF8_LOCALE_ONLY
+ const wxScopedCharBuffer mb_str(const wxMBConv& conv = wxConvLibc) const
+ {
+ return AsCharBuf(conv);
+ }
+#endif // wxUSE_UTF8_LOCALE_ONLY/!wxUSE_UTF8_LOCALE_ONLY
+
+ const wxWX2MBbuf mbc_str() const { return mb_str(*wxConvCurrent); }
+
+#if wxUSE_UNICODE_WCHAR
+ const wchar_t* wc_str() const { return wx_str(); }
+#elif wxUSE_UNICODE_UTF8
+ const wxScopedWCharBuffer wc_str() const
+ { return AsWCharBuf(wxMBConvStrictUTF8()); }
+#endif
+ // for compatibility with !wxUSE_UNICODE version
+ const wxWX2WCbuf wc_str(const wxMBConv& WXUNUSED(conv)) const
+ { return wc_str(); }
+
+#if wxMBFILES
+ const wxScopedCharBuffer fn_str() const { return mb_str(wxConvFile); }
+#else // !wxMBFILES
+ const wxWX2WCbuf fn_str() const { return wc_str(); }
+#endif // wxMBFILES/!wxMBFILES
+
+#else // ANSI
+ const char* mb_str() const { return wx_str(); }
+
+ // for compatibility with wxUSE_UNICODE version
+ const char* mb_str(const wxMBConv& WXUNUSED(conv)) const { return wx_str(); }
+
+ const wxWX2MBbuf mbc_str() const { return mb_str(); }
+
+ const wxScopedWCharBuffer wc_str(const wxMBConv& conv = wxConvLibc) const
+ { return AsWCharBuf(conv); }
+
+ const wxScopedCharBuffer fn_str() const
+ { return wxConvFile.cWC2WX( wc_str( wxConvLibc ) ); }
+#endif // Unicode/ANSI
+
+#if wxUSE_UNICODE_UTF8
+ const wxScopedWCharBuffer t_str() const { return wc_str(); }
+#elif wxUSE_UNICODE_WCHAR
+ const wchar_t* t_str() const { return wx_str(); }
+#else
+ const char* t_str() const { return wx_str(); }
+#endif
+
+
+ // overloaded assignment
+ // from another wxString
+ wxString& operator=(const wxString& stringSrc)
+ {
+ if ( this != &stringSrc )
+ {
+ wxSTRING_INVALIDATE_CACHE();
+
+ m_impl = stringSrc.m_impl;
+ }
+
+ return *this;
+ }
+
+ wxString& operator=(const wxCStrData& cstr)
+ { return *this = cstr.AsString(); }
+ // from a character
+ wxString& operator=(wxUniChar ch)
+ {
+ wxSTRING_INVALIDATE_CACHE();
+
+#if wxUSE_UNICODE_UTF8
+ if ( !ch.IsAscii() )
+ m_impl = wxStringOperations::EncodeChar(ch);
+ else
+#endif // wxUSE_UNICODE_UTF8
+ m_impl = (wxStringCharType)ch;
+ return *this;
+ }
+
+ wxString& operator=(wxUniCharRef ch)
+ { return operator=((wxUniChar)ch); }
+ wxString& operator=(char ch)
+ { return operator=(wxUniChar(ch)); }
+ wxString& operator=(unsigned char ch)
+ { return operator=(wxUniChar(ch)); }
+ wxString& operator=(wchar_t ch)
+ { return operator=(wxUniChar(ch)); }
+ // from a C string - STL probably will crash on NULL,
+ // so we need to compensate in that case
+#if wxUSE_STL_BASED_WXSTRING
+ wxString& operator=(const char *psz)
+ {
+ wxSTRING_INVALIDATE_CACHE();
+
+ if ( psz )
+ m_impl = ImplStr(psz);
+ else
+ clear();
+
+ return *this;
+ }
+
+ wxString& operator=(const wchar_t *pwz)
+ {
+ wxSTRING_INVALIDATE_CACHE();
+
+ if ( pwz )
+ m_impl = ImplStr(pwz);
+ else
+ clear();
+
+ return *this;
+ }
+#else // !wxUSE_STL_BASED_WXSTRING
+ wxString& operator=(const char *psz)
+ {
+ wxSTRING_INVALIDATE_CACHE();
+
+ m_impl = ImplStr(psz);
+
+ return *this;
+ }
+
+ wxString& operator=(const wchar_t *pwz)
+ {
+ wxSTRING_INVALIDATE_CACHE();
+
+ m_impl = ImplStr(pwz);
+
+ return *this;
+ }
+#endif // wxUSE_STL_BASED_WXSTRING/!wxUSE_STL_BASED_WXSTRING
+
+ wxString& operator=(const unsigned char *psz)
+ { return operator=((const char*)psz); }
+
+ // from wxScopedWCharBuffer
+ wxString& operator=(const wxScopedWCharBuffer& s)
+ { return assign(s); }
+ // from wxScopedCharBuffer
+ wxString& operator=(const wxScopedCharBuffer& s)
+ { return assign(s); }
+
+ // string concatenation
+ // in place concatenation
+ /*
+ Concatenate and return the result. Note that the left to right
+ associativity of << allows to write things like "str << str1 << str2
+ << ..." (unlike with +=)
+ */
+ // string += string
+ wxString& operator<<(const wxString& s)
+ {
+#if WXWIN_COMPATIBILITY_2_8 && !wxUSE_STL_BASED_WXSTRING && !wxUSE_UNICODE_UTF8
+ wxASSERT_MSG( s.IsValid(),
+ _T("did you forget to call UngetWriteBuf()?") );
+#endif
+
+ append(s);
+ return *this;
+ }
+ // string += C string
+ wxString& operator<<(const char *psz)
+ { append(psz); return *this; }
+ wxString& operator<<(const wchar_t *pwz)
+ { append(pwz); return *this; }
+ wxString& operator<<(const wxCStrData& psz)
+ { append(psz.AsString()); return *this; }
+ // string += char
+ wxString& operator<<(wxUniChar ch) { append(1, ch); return *this; }
+ wxString& operator<<(wxUniCharRef ch) { append(1, ch); return *this; }
+ wxString& operator<<(char ch) { append(1, ch); return *this; }
+ wxString& operator<<(unsigned char ch) { append(1, ch); return *this; }
+ wxString& operator<<(wchar_t ch) { append(1, ch); return *this; }
+
+ // string += buffer (i.e. from wxGetString)
+ wxString& operator<<(const wxScopedWCharBuffer& s)
+ { return append(s); }
+ wxString& operator<<(const wxScopedCharBuffer& s)
+ { return append(s); }
+
+ // string += C string
+ wxString& Append(const wxString& s)
+ {
+ // test for empty() to share the string if possible
+ if ( empty() )
+ *this = s;
+ else
+ append(s);
+ return *this;
+ }
+ wxString& Append(const char* psz)
+ { append(psz); return *this; }
+ wxString& Append(const wchar_t* pwz)
+ { append(pwz); return *this; }
+ wxString& Append(const wxCStrData& psz)
+ { append(psz); return *this; }
+ wxString& Append(const wxScopedCharBuffer& psz)
+ { append(psz); return *this; }
+ wxString& Append(const wxScopedWCharBuffer& psz)
+ { append(psz); return *this; }
+ wxString& Append(const char* psz, size_t nLen)
+ { append(psz, nLen); return *this; }
+ wxString& Append(const wchar_t* pwz, size_t nLen)
+ { append(pwz, nLen); return *this; }
+ wxString& Append(const wxCStrData& psz, size_t nLen)
+ { append(psz, nLen); return *this; }
+ wxString& Append(const wxScopedCharBuffer& psz, size_t nLen)
+ { append(psz, nLen); return *this; }
+ wxString& Append(const wxScopedWCharBuffer& psz, size_t nLen)
+ { append(psz, nLen); return *this; }
+ // append count copies of given character
+ wxString& Append(wxUniChar ch, size_t count = 1u)
+ { append(count, ch); return *this; }
+ wxString& Append(wxUniCharRef ch, size_t count = 1u)
+ { append(count, ch); return *this; }
+ wxString& Append(char ch, size_t count = 1u)
+ { append(count, ch); return *this; }
+ wxString& Append(unsigned char ch, size_t count = 1u)
+ { append(count, ch); return *this; }
+ wxString& Append(wchar_t ch, size_t count = 1u)
+ { append(count, ch); return *this; }
+
+ // prepend a string, return the string itself
+ wxString& Prepend(const wxString& str)
+ { *this = str + *this; return *this; }
+
+ // non-destructive concatenation
+ // two strings
+ friend wxString WXDLLIMPEXP_BASE operator+(const wxString& string1,
+ const wxString& string2);
+ // string with a single char
+ friend wxString WXDLLIMPEXP_BASE operator+(const wxString& string, wxUniChar ch);
+ // char with a string
+ friend wxString WXDLLIMPEXP_BASE operator+(wxUniChar ch, const wxString& string);
+ // string with C string
+ friend wxString WXDLLIMPEXP_BASE operator+(const wxString& string,
+ const char *psz);
+ friend wxString WXDLLIMPEXP_BASE operator+(const wxString& string,
+ const wchar_t *pwz);
+ // C string with string
+ friend wxString WXDLLIMPEXP_BASE operator+(const char *psz,
+ const wxString& string);
+ friend wxString WXDLLIMPEXP_BASE operator+(const wchar_t *pwz,
+ const wxString& string);
+
+ // stream-like functions
+ // insert an int into string
+ wxString& operator<<(int i)
+ { return (*this) << Format(_T("%d"), i); }
+ // insert an unsigned int into string
+ wxString& operator<<(unsigned int ui)
+ { return (*this) << Format(_T("%u"), ui); }
+ // insert a long into string
+ wxString& operator<<(long l)
+ { return (*this) << Format(_T("%ld"), l); }
+ // insert an unsigned long into string
+ wxString& operator<<(unsigned long ul)
+ { return (*this) << Format(_T("%lu"), ul); }
+#if defined wxLongLong_t && !defined wxLongLongIsLong
+ // insert a long long if they exist and aren't longs
+ wxString& operator<<(wxLongLong_t ll)
+ {
+ const wxChar *fmt = _T("%") wxLongLongFmtSpec _T("d");
+ return (*this) << Format(fmt, ll);
+ }
+ // insert an unsigned long long
+ wxString& operator<<(wxULongLong_t ull)
+ {
+ const wxChar *fmt = _T("%") wxLongLongFmtSpec _T("u");
+ return (*this) << Format(fmt , ull);
+ }
+#endif // wxLongLong_t && !wxLongLongIsLong
+ // insert a float into string
+ wxString& operator<<(float f)
+ { return (*this) << Format(_T("%f"), f); }
+ // insert a double into string
+ wxString& operator<<(double d)
+ { return (*this) << Format(_T("%g"), d); }
+
+ // string comparison
+ // case-sensitive comparison (returns a value < 0, = 0 or > 0)
+ int Cmp(const char *psz) const
+ { return compare(psz); }
+ int Cmp(const wchar_t *pwz) const
+ { return compare(pwz); }
+ int Cmp(const wxString& s) const
+ { return compare(s); }
+ int Cmp(const wxCStrData& s) const
+ { return compare(s); }
+ int Cmp(const wxScopedCharBuffer& s) const
+ { return compare(s); }
+ int Cmp(const wxScopedWCharBuffer& s) const
+ { return compare(s); }
+ // same as Cmp() but not case-sensitive
+ int CmpNoCase(const wxString& s) const;
+
+ // test for the string equality, either considering case or not
+ // (if compareWithCase then the case matters)
+ bool IsSameAs(const wxString& str, bool compareWithCase = true) const
+ {
+#if !wxUSE_UNICODE_UTF8
+ // in UTF-8 build, length() is O(n) and doing this would be _slower_
+ if ( length() != str.length() )
+ return false;
+#endif
+ return (compareWithCase ? Cmp(str) : CmpNoCase(str)) == 0;
+ }
+ bool IsSameAs(const char *str, bool compareWithCase = true) const
+ { return (compareWithCase ? Cmp(str) : CmpNoCase(str)) == 0; }
+ bool IsSameAs(const wchar_t *str, bool compareWithCase = true) const
+ { return (compareWithCase ? Cmp(str) : CmpNoCase(str)) == 0; }
+
+ bool IsSameAs(const wxCStrData& str, bool compareWithCase = true) const
+ { return IsSameAs(str.AsString(), compareWithCase); }
+ bool IsSameAs(const wxScopedCharBuffer& str, bool compareWithCase = true) const
+ { return IsSameAs(str.data(), compareWithCase); }
+ bool IsSameAs(const wxScopedWCharBuffer& str, bool compareWithCase = true) const
+ { return IsSameAs(str.data(), compareWithCase); }
+ // comparison with a single character: returns true if equal
+ bool IsSameAs(wxUniChar c, bool compareWithCase = true) const;
+ // FIXME-UTF8: remove these overloads
+ bool IsSameAs(wxUniCharRef c, bool compareWithCase = true) const
+ { return IsSameAs(wxUniChar(c), compareWithCase); }
+ bool IsSameAs(char c, bool compareWithCase = true) const
+ { return IsSameAs(wxUniChar(c), compareWithCase); }
+ bool IsSameAs(unsigned char c, bool compareWithCase = true) const
+ { return IsSameAs(wxUniChar(c), compareWithCase); }
+ bool IsSameAs(wchar_t c, bool compareWithCase = true) const
+ { return IsSameAs(wxUniChar(c), compareWithCase); }
+ bool IsSameAs(int c, bool compareWithCase = true) const
+ { return IsSameAs(wxUniChar(c), compareWithCase); }
+
+ // simple sub-string extraction
+ // return substring starting at nFirst of length nCount (or till the end
+ // if nCount = default value)
+ wxString Mid(size_t nFirst, size_t nCount = npos) const;
+
+ // operator version of Mid()
+ wxString operator()(size_t start, size_t len) const
+ { return Mid(start, len); }
+
+ // check if the string starts with the given prefix and return the rest
+ // of the string in the provided pointer if it is not NULL; otherwise
+ // return false
+ bool StartsWith(const wxString& prefix, wxString *rest = NULL) const;
+ // check if the string ends with the given suffix and return the
+ // beginning of the string before the suffix in the provided pointer if
+ // it is not NULL; otherwise return false
+ bool EndsWith(const wxString& suffix, wxString *rest = NULL) const;
+
+ // get first nCount characters
+ wxString Left(size_t nCount) const;
+ // get last nCount characters
+ wxString Right(size_t nCount) const;
+ // get all characters before the first occurrence of ch
+ // (returns the whole string if ch not found)
+ wxString BeforeFirst(wxUniChar ch) const;
+ // get all characters before the last occurrence of ch
+ // (returns empty string if ch not found)
+ wxString BeforeLast(wxUniChar ch) const;
+ // get all characters after the first occurrence of ch
+ // (returns empty string if ch not found)
+ wxString AfterFirst(wxUniChar ch) const;
+ // get all characters after the last occurrence of ch
+ // (returns the whole string if ch not found)
+ wxString AfterLast(wxUniChar ch) const;
+
+ // for compatibility only, use more explicitly named functions above
+ wxString Before(wxUniChar ch) const { return BeforeLast(ch); }
+ wxString After(wxUniChar ch) const { return AfterFirst(ch); }
+
+ // case conversion
+ // convert to upper case in place, return the string itself
+ wxString& MakeUpper();
+ // convert to upper case, return the copy of the string
+ wxString Upper() const { return wxString(*this).MakeUpper(); }
+ // convert to lower case in place, return the string itself
+ wxString& MakeLower();
+ // convert to lower case, return the copy of the string
+ wxString Lower() const { return wxString(*this).MakeLower(); }
+ // convert the first character to the upper case and the rest to the
+ // lower one, return the modified string itself
+ wxString& MakeCapitalized();
+ // convert the first character to the upper case and the rest to the
+ // lower one, return the copy of the string
+ wxString Capitalize() const { return wxString(*this).MakeCapitalized(); }
+
+ // trimming/padding whitespace (either side) and truncating
+ // remove spaces from left or from right (default) side
+ wxString& Trim(bool bFromRight = true);
+ // add nCount copies chPad in the beginning or at the end (default)
+ wxString& Pad(size_t nCount, wxUniChar chPad = wxT(' '), bool bFromRight = true);
+
+ // searching and replacing
+ // searching (return starting index, or -1 if not found)
+ int Find(wxUniChar ch, bool bFromEnd = false) const; // like strchr/strrchr
+ int Find(wxUniCharRef ch, bool bFromEnd = false) const
+ { return Find(wxUniChar(ch), bFromEnd); }
+ int Find(char ch, bool bFromEnd = false) const
+ { return Find(wxUniChar(ch), bFromEnd); }
+ int Find(unsigned char ch, bool bFromEnd = false) const
+ { return Find(wxUniChar(ch), bFromEnd); }
+ int Find(wchar_t ch, bool bFromEnd = false) const
+ { return Find(wxUniChar(ch), bFromEnd); }
+ // searching (return starting index, or -1 if not found)
+ int Find(const wxString& sub) const // like strstr
+ {
+ size_type idx = find(sub);
+ return (idx == npos) ? wxNOT_FOUND : (int)idx;
+ }
+ int Find(const char *sub) const // like strstr
+ {
+ size_type idx = find(sub);
+ return (idx == npos) ? wxNOT_FOUND : (int)idx;
+ }
+ int Find(const wchar_t *sub) const // like strstr
+ {
+ size_type idx = find(sub);
+ return (idx == npos) ? wxNOT_FOUND : (int)idx;
+ }
+
+ int Find(const wxCStrData& sub) const
+ { return Find(sub.AsString()); }
+ int Find(const wxScopedCharBuffer& sub) const
+ { return Find(sub.data()); }
+ int Find(const wxScopedWCharBuffer& sub) const
+ { return Find(sub.data()); }
+
+ // replace first (or all of bReplaceAll) occurrences of substring with
+ // another string, returns the number of replacements made
+ size_t Replace(const wxString& strOld,
+ const wxString& strNew,
+ bool bReplaceAll = true);
+
+ // check if the string contents matches a mask containing '*' and '?'
+ bool Matches(const wxString& mask) const;
+
+ // conversion to numbers: all functions return true only if the whole
+ // string is a number and put the value of this number into the pointer
+ // provided, the base is the numeric base in which the conversion should be
+ // done and must be comprised between 2 and 36 or be 0 in which case the
+ // standard C rules apply (leading '0' => octal, "0x" => hex)
+ // convert to a signed integer
+ bool ToLong(long *val, int base = 10) const;
+ // convert to an unsigned integer
+ bool ToULong(unsigned long *val, int base = 10) const;
+ // convert to wxLongLong
+#if defined(wxLongLong_t)
+ bool ToLongLong(wxLongLong_t *val, int base = 10) const;
+ // convert to wxULongLong
+ bool ToULongLong(wxULongLong_t *val, int base = 10) const;
+#endif // wxLongLong_t
+ // convert to a double
+ bool ToDouble(double *val) const;
+
+#if wxUSE_XLOCALE
+ // conversions to numbers using C locale
+ // convert to a signed integer
+ bool ToCLong(long *val, int base = 10) const;
+ // convert to an unsigned integer
+ bool ToCULong(unsigned long *val, int base = 10) const;
+ // convert to a double
+ bool ToCDouble(double *val) const;
+#endif
+
+#ifndef wxNEEDS_WXSTRING_PRINTF_MIXIN
+ // formatted input/output
+ // as sprintf(), returns the number of characters written or < 0 on error
+ // (take 'this' into account in attribute parameter count)
+ // int Printf(const wxString& format, ...);
+ WX_DEFINE_VARARG_FUNC(int, Printf, 1, (const wxFormatString&),
+ DoPrintfWchar, DoPrintfUtf8)
+#ifdef __WATCOMC__
+ // workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351
+ WX_VARARG_WATCOM_WORKAROUND(int, Printf, 1, (const wxString&),
+ (wxFormatString(f1)));
+ WX_VARARG_WATCOM_WORKAROUND(int, Printf, 1, (const wxCStrData&),
+ (wxFormatString(f1)));
+ WX_VARARG_WATCOM_WORKAROUND(int, Printf, 1, (const char*),
+ (wxFormatString(f1)));
+ WX_VARARG_WATCOM_WORKAROUND(int, Printf, 1, (const wchar_t*),
+ (wxFormatString(f1)));
+#endif
+#endif // !wxNEEDS_WXSTRING_PRINTF_MIXIN
+ // as vprintf(), returns the number of characters written or < 0 on error
+ int PrintfV(const wxString& format, va_list argptr);
+
+#ifndef wxNEEDS_WXSTRING_PRINTF_MIXIN
+ // returns the string containing the result of Printf() to it
+ // static wxString Format(const wxString& format, ...) WX_ATTRIBUTE_PRINTF_1;
+ WX_DEFINE_VARARG_FUNC(static wxString, Format, 1, (const wxFormatString&),
+ DoFormatWchar, DoFormatUtf8)
+#ifdef __WATCOMC__
+ // workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351
+ WX_VARARG_WATCOM_WORKAROUND(static wxString, Format, 1, (const wxString&),
+ (wxFormatString(f1)));
+ WX_VARARG_WATCOM_WORKAROUND(static wxString, Format, 1, (const wxCStrData&),
+ (wxFormatString(f1)));
+ WX_VARARG_WATCOM_WORKAROUND(static wxString, Format, 1, (const char*),
+ (wxFormatString(f1)));
+ WX_VARARG_WATCOM_WORKAROUND(static wxString, Format, 1, (const wchar_t*),
+ (wxFormatString(f1)));
+#endif
+#endif
+ // the same as above, but takes a va_list
+ static wxString FormatV(const wxString& format, va_list argptr);
+
+ // raw access to string memory
+ // ensure that string has space for at least nLen characters
+ // only works if the data of this string is not shared
+ bool Alloc(size_t nLen) { reserve(nLen); return capacity() >= nLen; }
+ // minimize the string's memory
+ // only works if the data of this string is not shared
+ bool Shrink();
+#if WXWIN_COMPATIBILITY_2_8 && !wxUSE_STL_BASED_WXSTRING && !wxUSE_UNICODE_UTF8
+ // These are deprecated, use wxStringBuffer or wxStringBufferLength instead
+ //
+ // get writable buffer of at least nLen bytes. Unget() *must* be called
+ // a.s.a.p. to put string back in a reasonable state!
+ wxDEPRECATED( wxStringCharType *GetWriteBuf(size_t nLen) );
+ // call this immediately after GetWriteBuf() has been used
+ wxDEPRECATED( void UngetWriteBuf() );
+ wxDEPRECATED( void UngetWriteBuf(size_t nLen) );
+#endif // WXWIN_COMPATIBILITY_2_8 && !wxUSE_STL_BASED_WXSTRING && wxUSE_UNICODE_UTF8
+
+ // wxWidgets version 1 compatibility functions
+
+ // use Mid()
+ wxString SubString(size_t from, size_t to) const
+ { return Mid(from, (to - from + 1)); }
+ // values for second parameter of CompareTo function
+ enum caseCompare {exact, ignoreCase};
+ // values for first parameter of Strip function
+ enum stripType {leading = 0x1, trailing = 0x2, both = 0x3};
+
+#ifndef wxNEEDS_WXSTRING_PRINTF_MIXIN
+ // use Printf()
+ // (take 'this' into account in attribute parameter count)
+ // int sprintf(const wxString& format, ...) WX_ATTRIBUTE_PRINTF_2;
+ WX_DEFINE_VARARG_FUNC(int, sprintf, 1, (const wxFormatString&),
+ DoPrintfWchar, DoPrintfUtf8)
+#ifdef __WATCOMC__
+ // workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351
+ WX_VARARG_WATCOM_WORKAROUND(int, sprintf, 1, (const wxString&),
+ (wxFormatString(f1)));
+ WX_VARARG_WATCOM_WORKAROUND(int, sprintf, 1, (const wxCStrData&),
+ (wxFormatString(f1)));
+ WX_VARARG_WATCOM_WORKAROUND(int, sprintf, 1, (const char*),
+ (wxFormatString(f1)));
+ WX_VARARG_WATCOM_WORKAROUND(int, sprintf, 1, (const wchar_t*),
+ (wxFormatString(f1)));
+#endif
+#endif // wxNEEDS_WXSTRING_PRINTF_MIXIN
+
+ // use Cmp()
+ int CompareTo(const wxChar* psz, caseCompare cmp = exact) const
+ { return cmp == exact ? Cmp(psz) : CmpNoCase(psz); }
+
+ // use length()
+ size_t Length() const { return length(); }
+ // Count the number of characters
+ int Freq(wxUniChar ch) const;
+ // use MakeLower
+ void LowerCase() { MakeLower(); }
+ // use MakeUpper
+ void UpperCase() { MakeUpper(); }
+ // use Trim except that it doesn't change this string
+ wxString Strip(stripType w = trailing) const;
+
+ // use Find (more general variants not yet supported)
+ size_t Index(const wxChar* psz) const { return Find(psz); }
+ size_t Index(wxUniChar ch) const { return Find(ch); }
+ // use Truncate
+ wxString& Remove(size_t pos) { return Truncate(pos); }
+ wxString& RemoveLast(size_t n = 1) { return Truncate(length() - n); }
+
+ wxString& Remove(size_t nStart, size_t nLen)
+ { return (wxString&)erase( nStart, nLen ); }
+
+ // use Find()
+ int First( wxUniChar ch ) const { return Find(ch); }
+ int First( wxUniCharRef ch ) const { return Find(ch); }
+ int First( char ch ) const { return Find(ch); }
+ int First( unsigned char ch ) const { return Find(ch); }
+ int First( wchar_t ch ) const { return Find(ch); }
+ int First( const wxString& str ) const { return Find(str); }
+ int Last( wxUniChar ch ) const { return Find(ch, true); }
+ bool Contains(const wxString& str) const { return Find(str) != wxNOT_FOUND; }
+
+ // use empty()
+ bool IsNull() const { return empty(); }
+
+ // std::string compatibility functions
+
+ // take nLen chars starting at nPos
+ wxString(const wxString& str, size_t nPos, size_t nLen)
+ { assign(str, nPos, nLen); }
+ // take all characters from first to last
+ wxString(const_iterator first, const_iterator last)
+ : m_impl(first.impl(), last.impl()) { }
+#if WXWIN_COMPATIBILITY_STRING_PTR_AS_ITER
+ // the 2 overloads below are for compatibility with the existing code using
+ // pointers instead of iterators
+ wxString(const char *first, const char *last)
+ {
+ SubstrBufFromMB str(ImplStr(first, last - first));
+ m_impl.assign(str.data, str.len);
+ }
+ wxString(const wchar_t *first, const wchar_t *last)
+ {
+ SubstrBufFromWC str(ImplStr(first, last - first));
+ m_impl.assign(str.data, str.len);
+ }
+ // and this one is needed to compile code adding offsets to c_str() result
+ wxString(const wxCStrData& first, const wxCStrData& last)
+ : m_impl(CreateConstIterator(first).impl(),
+ CreateConstIterator(last).impl())
+ {
+ wxASSERT_MSG( first.m_str == last.m_str,
+ _T("pointers must be into the same string") );
+ }
+#endif // WXWIN_COMPATIBILITY_STRING_PTR_AS_ITER
+
+ // lib.string.modifiers
+ // append elements str[pos], ..., str[pos+n]
+ wxString& append(const wxString& str, size_t pos, size_t n)
+ {
+ wxSTRING_UPDATE_CACHED_LENGTH(n);
+
+ size_t from, len;
+ str.PosLenToImpl(pos, n, &from, &len);
+ m_impl.append(str.m_impl, from, len);
+ return *this;
+ }
+ // append a string
+ wxString& append(const wxString& str)
+ {
+ wxSTRING_UPDATE_CACHED_LENGTH(str.length());
+
+ m_impl.append(str.m_impl);
+ return *this;
+ }
+
+ // append first n (or all if n == npos) characters of sz
+ wxString& append(const char *sz)
+ {
+ wxSTRING_INVALIDATE_CACHED_LENGTH();
+
+ m_impl.append(ImplStr(sz));
+ return *this;
+ }
+
+ wxString& append(const wchar_t *sz)
+ {
+ wxSTRING_INVALIDATE_CACHED_LENGTH();
+
+ m_impl.append(ImplStr(sz));
+ return *this;
+ }
+
+ wxString& append(const char *sz, size_t n)
+ {
+ wxSTRING_INVALIDATE_CACHED_LENGTH();
+
+ SubstrBufFromMB str(ImplStr(sz, n));
+ m_impl.append(str.data, str.len);
+ return *this;
+ }
+ wxString& append(const wchar_t *sz, size_t n)
+ {
+ wxSTRING_UPDATE_CACHED_LENGTH(n);
+
+ SubstrBufFromWC str(ImplStr(sz, n));
+ m_impl.append(str.data, str.len);
+ return *this;
+ }
+
+ wxString& append(const wxCStrData& str)
+ { return append(str.AsString()); }
+ wxString& append(const wxScopedCharBuffer& str)
+ { return append(str.data(), str.length()); }
+ wxString& append(const wxScopedWCharBuffer& str)
+ { return append(str.data(), str.length()); }
+ wxString& append(const wxCStrData& str, size_t n)
+ { return append(str.AsString(), 0, n); }
+ wxString& append(const wxScopedCharBuffer& str, size_t n)
+ { return append(str.data(), n); }
+ wxString& append(const wxScopedWCharBuffer& str, size_t n)
+ { return append(str.data(), n); }
+
+ // append n copies of ch
+ wxString& append(size_t n, wxUniChar ch)
+ {
+#if wxUSE_UNICODE_UTF8
+ if ( !ch.IsAscii() )
+ {
+ wxSTRING_INVALIDATE_CACHED_LENGTH();
+
+ m_impl.append(wxStringOperations::EncodeNChars(n, ch));
+ }
+ else // ASCII
+#endif
+ {
+ wxSTRING_UPDATE_CACHED_LENGTH(n);
+
+ m_impl.append(n, (wxStringCharType)ch);
+ }
+
+ return *this;
+ }
+
+ wxString& append(size_t n, wxUniCharRef ch)
+ { return append(n, wxUniChar(ch)); }
+ wxString& append(size_t n, char ch)
+ { return append(n, wxUniChar(ch)); }
+ wxString& append(size_t n, unsigned char ch)
+ { return append(n, wxUniChar(ch)); }
+ wxString& append(size_t n, wchar_t ch)
+ { return append(n, wxUniChar(ch)); }
+
+ // append from first to last
+ wxString& append(const_iterator first, const_iterator last)
+ {
+ 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();
+ }