+ size_t LenToImpl(size_t len) const
+ {
+ size_t pos, len2;
+ PosLenToImpl(0, len, &pos, &len2);
+ return len2;
+ }
+
+ size_t PosFromImpl(size_t pos) const
+ {
+ if ( pos == 0 || pos == npos )
+ return pos;
+ else
+ return const_iterator(this, m_impl.begin() + pos) - begin();
+ }
+#endif // !wxUSE_UNICODE_UTF8/wxUSE_UNICODE_UTF8
+
+public:
+ // standard types
+ typedef wxUniChar value_type;
+ typedef wxUniChar char_type;
+ typedef wxUniCharRef reference;
+ typedef wxChar* pointer;
+ typedef const wxChar* const_pointer;
+
+ typedef size_t size_type;
+ typedef wxUniChar const_reference;
+
+#if wxUSE_STD_STRING
+ #if wxUSE_UNICODE_UTF8
+ // random access is not O(1), as required by Random Access Iterator
+ #define WX_STR_ITERATOR_TAG std::bidirectional_iterator_tag
+ #else
+ #define WX_STR_ITERATOR_TAG std::random_access_iterator_tag
+ #endif
+ #define WX_DEFINE_ITERATOR_CATEGORY(cat) typedef cat iterator_category;
+#else
+ // not defining iterator_category at all in this case is better than defining
+ // it as some dummy type -- at least it results in more intelligible error
+ // messages
+ #define WX_DEFINE_ITERATOR_CATEGORY(cat)
+#endif
+
+ #define WX_STR_ITERATOR_IMPL(iterator_name, pointer_type, reference_type) \
+ private: \
+ typedef wxStringImpl::iterator_name underlying_iterator; \
+ public: \
+ WX_DEFINE_ITERATOR_CATEGORY(WX_STR_ITERATOR_TAG) \
+ typedef wxUniChar value_type; \
+ typedef int difference_type; \
+ typedef reference_type reference; \
+ typedef pointer_type pointer; \
+ \
+ reference operator[](size_t n) const { return *(*this + n); } \
+ \
+ iterator_name& operator++() \
+ { wxStringOperations::IncIter(m_cur); return *this; } \
+ iterator_name& operator--() \
+ { wxStringOperations::DecIter(m_cur); return *this; } \
+ iterator_name operator++(int) \
+ { \
+ iterator_name tmp = *this; \
+ wxStringOperations::IncIter(m_cur); \
+ return tmp; \
+ } \
+ iterator_name operator--(int) \
+ { \
+ iterator_name tmp = *this; \
+ wxStringOperations::DecIter(m_cur); \
+ return tmp; \
+ } \
+ \
+ iterator_name& operator+=(ptrdiff_t n) \
+ { \
+ m_cur = wxStringOperations::AddToIter(m_cur, n); \
+ return *this; \
+ } \
+ iterator_name& operator-=(ptrdiff_t n) \
+ { \
+ m_cur = wxStringOperations::AddToIter(m_cur, -n); \
+ return *this; \
+ } \
+ \
+ difference_type operator-(const iterator_name& i) const \
+ { return wxStringOperations::DiffIters(m_cur, i.m_cur); } \
+ \
+ bool operator==(const iterator_name& i) const \
+ { return m_cur == i.m_cur; } \
+ bool operator!=(const iterator_name& i) const \
+ { return m_cur != i.m_cur; } \
+ \
+ bool operator<(const iterator_name& i) const \
+ { return m_cur < i.m_cur; } \
+ bool operator>(const iterator_name& i) const \
+ { return m_cur > i.m_cur; } \
+ bool operator<=(const iterator_name& i) const \
+ { return m_cur <= i.m_cur; } \
+ bool operator>=(const iterator_name& i) const \
+ { return m_cur >= i.m_cur; } \
+ \
+ private: \
+ /* for internal wxString use only: */ \
+ underlying_iterator impl() const { return m_cur; } \
+ \
+ friend class wxString; \
+ friend class wxCStrData; \
+ \
+ private: \
+ underlying_iterator m_cur
+
+ class WXDLLIMPEXP_FWD_BASE const_iterator;
+
+#if wxUSE_UNICODE_UTF8
+ // NB: In UTF-8 build, (non-const) iterator needs to keep reference
+ // to the underlying wxStringImpl, because UTF-8 is variable-length
+ // encoding and changing the value pointer to by an iterator (using
+ // its operator*) requires calling wxStringImpl::replace() if the old
+ // and new values differ in their encoding's length.
+ //
+ // Furthermore, the replace() call may invalid all iterators for the
+ // string, so we have to keep track of outstanding iterators and update
+ // them if replace() happens.
+ //
+ // This is implemented by maintaining linked list of iterators for every
+ // string and traversing it in wxUniCharRef::operator=(). Head of the
+ // list is stored in wxString. (FIXME-UTF8)
+
+ class WXDLLIMPEXP_BASE iterator
+ {
+ WX_STR_ITERATOR_IMPL(iterator, wxChar*, wxUniCharRef);
+
+ public:
+ iterator() {}
+ iterator(const iterator& i)
+ : m_cur(i.m_cur), m_node(i.str(), &m_cur) {}
+ iterator& operator=(const iterator& i)
+ {
+ if (&i != this)
+ {
+ m_cur = i.m_cur;
+ m_node.set(i.str(), &m_cur);
+ }
+ return *this;
+ }
+
+ reference operator*()
+ { return wxUniCharRef::CreateForString(*str(), m_cur); }
+
+ iterator operator+(ptrdiff_t n) const
+ { return iterator(str(), wxStringOperations::AddToIter(m_cur, n)); }
+ iterator operator-(ptrdiff_t n) const
+ { return iterator(str(), wxStringOperations::AddToIter(m_cur, -n)); }
+
+ // Normal iterators need to be comparable with the const_iterators so
+ // declare the comparison operators and implement them below after the
+ // full const_iterator declaration.
+ bool operator==(const const_iterator& i) const;
+ bool operator!=(const const_iterator& i) const;
+ bool operator<(const const_iterator& i) const;
+ bool operator>(const const_iterator& i) const;
+ bool operator<=(const const_iterator& i) const;
+ bool operator>=(const const_iterator& i) const;
+
+ private:
+ iterator(wxString *wxstr, underlying_iterator ptr)
+ : m_cur(ptr), m_node(wxstr, &m_cur) {}
+
+ wxString* str() const { return const_cast<wxString*>(m_node.m_str); }
+
+ wxStringIteratorNode m_node;
+
+ friend class const_iterator;
+ };
+
+ class WXDLLIMPEXP_BASE const_iterator
+ {
+ // NB: reference_type is intentionally value, not reference, the character
+ // may be encoded differently in wxString data:
+ WX_STR_ITERATOR_IMPL(const_iterator, const wxChar*, wxUniChar);
+
+ public:
+ const_iterator() {}
+ const_iterator(const const_iterator& i)
+ : m_cur(i.m_cur), m_node(i.str(), &m_cur) {}
+ const_iterator(const iterator& i)
+ : m_cur(i.m_cur), m_node(i.str(), &m_cur) {}
+
+ const_iterator& operator=(const const_iterator& i)
+ {
+ if (&i != this)
+ {
+ m_cur = i.m_cur;
+ m_node.set(i.str(), &m_cur);
+ }
+ return *this;
+ }
+ const_iterator& operator=(const iterator& i)
+ { m_cur = i.m_cur; m_node.set(i.str(), &m_cur); return *this; }
+
+ reference operator*() const
+ { return wxStringOperations::DecodeChar(m_cur); }
+
+ const_iterator operator+(ptrdiff_t n) const
+ { return const_iterator(str(), wxStringOperations::AddToIter(m_cur, n)); }
+ const_iterator operator-(ptrdiff_t n) const
+ { return const_iterator(str(), wxStringOperations::AddToIter(m_cur, -n)); }
+
+ // Notice that comparison operators taking non-const iterator are not
+ // needed here because of the implicit conversion from non-const iterator
+ // to const ones ensure that the versions for const_iterator declared
+ // inside WX_STR_ITERATOR_IMPL can be used.
+
+ private:
+ // for internal wxString use only:
+ const_iterator(const wxString *wxstr, underlying_iterator ptr)
+ : m_cur(ptr), m_node(wxstr, &m_cur) {}
+
+ const wxString* str() const { return m_node.m_str; }
+
+ wxStringIteratorNode m_node;
+ };
+
+ size_t IterToImplPos(wxString::iterator i) const
+ { return wxStringImpl::const_iterator(i.impl()) - m_impl.begin(); }
+
+ iterator GetIterForNthChar(size_t n)
+ { return iterator(this, m_impl.begin() + PosToImpl(n)); }
+ const_iterator GetIterForNthChar(size_t n) const
+ { return const_iterator(this, m_impl.begin() + PosToImpl(n)); }
+#else // !wxUSE_UNICODE_UTF8
+
+ class WXDLLIMPEXP_BASE iterator
+ {
+ WX_STR_ITERATOR_IMPL(iterator, wxChar*, wxUniCharRef);
+
+ public:
+ iterator() {}
+ iterator(const iterator& i) : m_cur(i.m_cur) {}
+
+ reference operator*()
+ { return wxUniCharRef::CreateForString(m_cur); }
+
+ iterator operator+(ptrdiff_t n) const
+ { return iterator(wxStringOperations::AddToIter(m_cur, n)); }
+ iterator operator-(ptrdiff_t n) const
+ { return iterator(wxStringOperations::AddToIter(m_cur, -n)); }
+
+ // As in UTF-8 case above, define comparison operators taking
+ // const_iterator too.
+ bool operator==(const const_iterator& i) const;
+ bool operator!=(const const_iterator& i) const;
+ bool operator<(const const_iterator& i) const;
+ bool operator>(const const_iterator& i) const;
+ bool operator<=(const const_iterator& i) const;
+ bool operator>=(const const_iterator& i) const;
+
+ private:
+ // for internal wxString use only:
+ iterator(underlying_iterator ptr) : m_cur(ptr) {}
+ iterator(wxString *WXUNUSED(str), underlying_iterator ptr) : m_cur(ptr) {}
+
+ friend class const_iterator;
+ };
+
+ class WXDLLIMPEXP_BASE const_iterator
+ {
+ // NB: reference_type is intentionally value, not reference, the character
+ // may be encoded differently in wxString data:
+ WX_STR_ITERATOR_IMPL(const_iterator, const wxChar*, wxUniChar);
+
+ public:
+ const_iterator() {}
+ const_iterator(const const_iterator& i) : m_cur(i.m_cur) {}
+ const_iterator(const iterator& i) : m_cur(i.m_cur) {}
+
+ reference operator*() const
+ { return wxStringOperations::DecodeChar(m_cur); }
+
+ const_iterator operator+(ptrdiff_t n) const
+ { return const_iterator(wxStringOperations::AddToIter(m_cur, n)); }
+ const_iterator operator-(ptrdiff_t n) const
+ { return const_iterator(wxStringOperations::AddToIter(m_cur, -n)); }
+
+ // As in UTF-8 case above, we don't need comparison operators taking
+ // iterator because we have an implicit conversion from iterator to
+ // const_iterator so the operators declared by WX_STR_ITERATOR_IMPL will
+ // be used.
+
+ private:
+ // for internal wxString use only:
+ const_iterator(underlying_iterator ptr) : m_cur(ptr) {}
+ const_iterator(const wxString *WXUNUSED(str), underlying_iterator ptr)
+ : m_cur(ptr) {}
+ };
+
+ iterator GetIterForNthChar(size_t n) { return begin() + n; }
+ const_iterator GetIterForNthChar(size_t n) const { return begin() + n; }
+#endif // wxUSE_UNICODE_UTF8/!wxUSE_UNICODE_UTF8
+
+ #undef WX_STR_ITERATOR_TAG
+ #undef WX_STR_ITERATOR_IMPL
+
+ friend class iterator;
+ friend class const_iterator;
+
+ template <typename T>
+ class reverse_iterator_impl
+ {
+ public:
+ typedef T iterator_type;
+
+ WX_DEFINE_ITERATOR_CATEGORY(typename T::iterator_category)
+ typedef typename T::value_type value_type;
+ typedef typename T::difference_type difference_type;
+ typedef typename T::reference reference;
+ typedef typename T::pointer *pointer;
+
+ reverse_iterator_impl() {}
+ reverse_iterator_impl(iterator_type i) : m_cur(i) {}
+ reverse_iterator_impl(const reverse_iterator_impl& ri)
+ : m_cur(ri.m_cur) {}
+
+ iterator_type base() const { return m_cur; }
+
+ reference operator*() const { return *(m_cur-1); }
+ reference operator[](size_t n) const { return *(*this + n); }
+
+ reverse_iterator_impl& operator++()
+ { --m_cur; return *this; }
+ reverse_iterator_impl operator++(int)
+ { reverse_iterator_impl tmp = *this; --m_cur; return tmp; }
+ reverse_iterator_impl& operator--()
+ { ++m_cur; return *this; }
+ reverse_iterator_impl operator--(int)
+ { reverse_iterator_impl tmp = *this; ++m_cur; return tmp; }
+
+ // NB: explicit <T> in the functions below is to keep BCC 5.5 happy
+ reverse_iterator_impl operator+(ptrdiff_t n) const
+ { return reverse_iterator_impl<T>(m_cur - n); }
+ reverse_iterator_impl operator-(ptrdiff_t n) const
+ { return reverse_iterator_impl<T>(m_cur + n); }
+ reverse_iterator_impl operator+=(ptrdiff_t n)
+ { m_cur -= n; return *this; }
+ reverse_iterator_impl operator-=(ptrdiff_t n)
+ { m_cur += n; return *this; }
+
+ unsigned operator-(const reverse_iterator_impl& i) const
+ { return i.m_cur - m_cur; }
+
+ bool operator==(const reverse_iterator_impl& ri) const
+ { return m_cur == ri.m_cur; }
+ bool operator!=(const reverse_iterator_impl& ri) const
+ { return !(*this == ri); }
+
+ bool operator<(const reverse_iterator_impl& i) const
+ { return m_cur > i.m_cur; }
+ bool operator>(const reverse_iterator_impl& i) const
+ { return m_cur < i.m_cur; }
+ bool operator<=(const reverse_iterator_impl& i) const
+ { return m_cur >= i.m_cur; }
+ bool operator>=(const reverse_iterator_impl& i) const
+ { return m_cur <= i.m_cur; }
+
+ private:
+ iterator_type m_cur;
+ };
+
+ typedef reverse_iterator_impl<iterator> reverse_iterator;
+ typedef reverse_iterator_impl<const_iterator> const_reverse_iterator;
+
+private:
+ // used to transform an expression built using c_str() (and hence of type
+ // wxCStrData) to an iterator into the string
+ static const_iterator CreateConstIterator(const wxCStrData& data)
+ {
+ return const_iterator(data.m_str,
+ (data.m_str->begin() + data.m_offset).impl());
+ }
+
+ // in UTF-8 STL build, creation from std::string requires conversion under
+ // non-UTF8 locales, so we can't have and use wxString(wxStringImpl) ctor;
+ // instead we define dummy type that lets us have wxString ctor for creation
+ // from wxStringImpl that couldn't be used by user code (in all other builds,
+ // "standard" ctors can be used):
+#if wxUSE_UNICODE_UTF8 && wxUSE_STL_BASED_WXSTRING
+ struct CtorFromStringImplTag {};
+
+ wxString(CtorFromStringImplTag* WXUNUSED(dummy), const wxStringImpl& src)
+ : m_impl(src) {}
+
+ static wxString FromImpl(const wxStringImpl& src)
+ { return wxString((CtorFromStringImplTag*)NULL, src); }
+#else
+ #if !wxUSE_STL_BASED_WXSTRING
+ wxString(const wxStringImpl& src) : m_impl(src) { }
+ // else: already defined as wxString(wxStdString) below
+ #endif
+ static wxString FromImpl(const wxStringImpl& src) { return wxString(src); }
+#endif
+
+public:
+ // constructors and destructor
+ // ctor for an empty string
+ wxString() {}
+
+ // 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_STD_STRING_CONV_IN_WXSTRING == 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
+
+ // Also always provide explicit conversions to std::[w]string in any case,
+ // see below for the implicit ones.
+#if wxUSE_STD_STRING
+ // We can avoid a copy if we already use this string type internally,
+ // otherwise we create a copy on the fly:
+ #if wxUSE_UNICODE_WCHAR && wxUSE_STL_BASED_WXSTRING
+ #define wxStringToStdWstringRetType const wxStdWideString&
+ const wxStdWideString& ToStdWstring() const { return m_impl; }
+ #else
+ // wxStringImpl is either not std::string or needs conversion
+ #define wxStringToStdWstringRetType wxStdWideString
+ wxStdWideString ToStdWstring() const
+ {
+#if wxUSE_UNICODE_WCHAR
+ wxScopedWCharBuffer buf =
+ wxScopedWCharBuffer::CreateNonOwned(m_impl.c_str(), m_impl.length());
+#else // !wxUSE_UNICODE_WCHAR
+ wxScopedWCharBuffer buf(wc_str());
+#endif
+
+ 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
+ #define wxStringToStdStringRetType const std::string&
+ const std::string& ToStdString() const { return m_impl; }
+ #else
+ // wxStringImpl is either not std::string or needs conversion
+ #define wxStringToStdStringRetType std::string
+ std::string ToStdString() const
+ {
+ wxScopedCharBuffer buf(mb_str());
+ return std::string(buf.data(), buf.length());
+ }
+ #endif
+
+#if wxUSE_STD_STRING_CONV_IN_WXSTRING
+ // Implicit conversions to std::[w]string are not provided by default as
+ // they conflict with the implicit conversions to "const char/wchar_t *"
+ // which we use for backwards compatibility but do provide them if
+ // explicitly requested.
+ operator wxStringToStdStringRetType() const { return ToStdString(); }
+ operator wxStringToStdWstringRetType() const { return ToStdWstring(); }
+#endif // wxUSE_STD_STRING_CONV_IN_WXSTRING
+
+#undef wxStringToStdStringRetType
+#undef wxStringToStdWstringRetType
+
+#endif // wxUSE_STD_STRING
+
+ 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(), wxT("wxString: index out of bounds") );
+ return *rbegin();
+ }
+
+ // get writable last character
+ wxUniCharRef Last()
+ {
+ wxASSERT_MSG( !empty(), wxT("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 if those conversions are enabled;
+ // 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_STD_STRING_CONV_IN_WXSTRING
+ 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_STD_STRING_CONV_IN_WXSTRING
+
+ // 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 wxScopedCharBuffer To8BitData() const
+ { return wxScopedCharBuffer::CreateNonOwned(wx_str(), length()); }
+#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(),
+ wxT("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(wxT("%d"), i); }
+ // insert an unsigned int into string
+ wxString& operator<<(unsigned int ui)
+ { return (*this) << Format(wxT("%u"), ui); }
+ // insert a long into string
+ wxString& operator<<(long l)
+ { return (*this) << Format(wxT("%ld"), l); }
+ // insert an unsigned long into string
+ wxString& operator<<(unsigned long ul)
+ { return (*this) << Format(wxT("%lu"), ul); }
+#ifdef wxHAS_LONG_LONG_T_DIFFERENT_FROM_LONG
+ // insert a long long if they exist and aren't longs
+ wxString& operator<<(wxLongLong_t ll)
+ {
+ return (*this) << Format("%" wxLongLongFmtSpec "d", ll);
+ }
+ // insert an unsigned long long
+ wxString& operator<<(wxULongLong_t ull)
+ {
+ return (*this) << Format("%" wxLongLongFmtSpec "u" , ull);
+ }
+#endif // wxHAS_LONG_LONG_T_DIFFERENT_FROM_LONG
+ // insert a float into string
+ wxString& operator<<(float f)
+ { return (*this) << Format(wxT("%f"), f); }
+ // insert a double into string
+ wxString& operator<<(double d)
+ { return (*this) << Format(wxT("%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) and also put everything
+ // following the first occurrence of ch into rest if it's non-NULL
+ wxString BeforeFirst(wxUniChar ch, wxString *rest = NULL) const;
+ // get all characters before the last occurrence of ch
+ // (returns empty string if ch not found) and also put everything
+ // following the last occurrence of ch into rest if it's non-NULL
+ wxString BeforeLast(wxUniChar ch, wxString *rest = NULL) 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);