+ // table of offsets to skip forward when iterating
+ static unsigned char ms_utf8IterTable[256];
+
+ static void IncIter(wxStringImpl::iterator& i)
+ {
+ wxASSERT( IsValidUtf8LeadByte(*i) );
+ i += ms_utf8IterTable[(unsigned char)*i];
+ }
+ static void IncIter(wxStringImpl::const_iterator& i)
+ {
+ wxASSERT( IsValidUtf8LeadByte(*i) );
+ i += ms_utf8IterTable[(unsigned char)*i];
+ }
+
+ static void DecIter(wxStringImpl::iterator& i);
+ static void DecIter(wxStringImpl::const_iterator& i);
+ static wxStringImpl::iterator AddToIter(wxStringImpl::iterator i, int n);
+ static wxStringImpl::const_iterator AddToIter(wxStringImpl::const_iterator i, int n);
+ static int DiffIters(wxStringImpl::const_iterator i1, wxStringImpl::const_iterator i2);
+ static int DiffIters(wxStringImpl::iterator i1, wxStringImpl::iterator i2);
+
+ struct Utf8CharBuffer
+ {
+ char data[5];
+ operator const char*() const { return data; }
+ };
+ static Utf8CharBuffer EncodeChar(wxUniChar ch);
+ // returns n copies of ch encoded in UTF-8 string
+ static wxCharBuffer EncodeNChars(size_t n, wxUniChar ch);
+
+ // returns the length of UTF-8 encoding of the character with lead byte 'c'
+ static size_t GetUtf8CharLength(char c)
+ {
+ wxASSERT( IsValidUtf8LeadByte(c) );
+ return ms_utf8IterTable[(unsigned char)c];
+ }
+
+ // decodes single UTF-8 character from UTF-8 string
+ // FIXME-UTF8: move EncodeChar/DecodeChar and other operations to separate
+ // class
+ static wxUniChar DecodeChar(wxStringImpl::const_iterator i)
+ { return wxUniCharRef::DecodeChar(i); }
+ friend class WXDLLIMPEXP_BASE wxUniCharRef;
+
+ size_t PosToImpl(size_t pos) const
+ {
+ if ( pos == 0 || pos == npos )
+ return pos;
+ else
+ return wxStringImpl::const_iterator(begin() + pos) - m_impl.begin();
+ }
+
+ void PosLenToImpl(size_t pos, size_t len, size_t *implPos, size_t *implLen) const;
+
+ 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(m_impl.begin() + pos) - begin();
+ }
+
+ size_t IterToImplPos(wxStringImpl::iterator i) const
+ { return wxStringImpl::const_iterator(i) - m_impl.begin(); }
+
+ // FIXME-UTF8: return as-is without copying under UTF8 locale, return
+ // converted string under other locales - needs wxCharBuffer
+ // changes
+ static wxCharBuffer ImplStr(const char* str,
+ const wxMBConv& conv = wxConvLibc)
+ { return ConvertStr(str, npos, conv).data; }
+ static SubstrBufFromMB ImplStr(const char* str, size_t n,
+ const wxMBConv& conv = wxConvLibc)
+ { return ConvertStr(str, n, conv); }
+
+ static wxCharBuffer ImplStr(const wchar_t* str)
+ { return ConvertStr(str, npos, wxConvUTF8).data; }
+ static SubstrBufFromWC ImplStr(const wchar_t* str, size_t n)
+ { return ConvertStr(str, n, wxConvUTF8); }
+#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_STL
+ #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
+#else
+ #define WX_STR_ITERATOR_TAG void /* dummy type */
+#endif
+
+ #define WX_STR_ITERATOR_IMPL(iterator_name, pointer_type, \
+ reference_type, reference_ctor) \
+ private: \
+ typedef wxStringImpl::iterator_name underlying_iterator; \
+ public: \
+ typedef WX_STR_ITERATOR_TAG iterator_category; \
+ typedef wxUniChar value_type; \
+ typedef int difference_type; \
+ typedef reference_type reference; \
+ typedef pointer_type pointer; \
+ \
+ reference operator*() const { return reference_ctor; } \
+ reference operator[](size_t n) const { return *(*this + n); } \
+ \
+ iterator_name& operator++() \
+ { wxString::IncIter(m_cur); return *this; } \
+ iterator_name& operator--() \
+ { wxString::DecIter(m_cur); return *this; } \
+ iterator_name operator++(int) \
+ { \
+ iterator_name tmp = *this; \
+ wxString::IncIter(m_cur); \
+ return tmp; \
+ } \
+ iterator_name operator--(int) \
+ { \
+ iterator_name tmp = *this; \
+ wxString::DecIter(m_cur); \
+ return tmp; \
+ } \
+ \
+ iterator_name& operator+=(int n) \
+ { m_cur = wxString::AddToIter(m_cur, n); return *this; } \
+ iterator_name& operator+=(size_t n) \
+ { m_cur = wxString::AddToIter(m_cur, (int)n); return *this; } \
+ iterator_name& operator-=(int n) \
+ { m_cur = wxString::AddToIter(m_cur, -n); return *this; } \
+ iterator_name& operator-=(size_t n) \
+ { m_cur = wxString::AddToIter(m_cur, -(int)n); return *this; } \
+ \
+ difference_type operator-(const iterator_name& i) const \
+ { return wxString::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: */ \
+ operator underlying_iterator() const { return m_cur; } \
+ \
+ friend class WXDLLIMPEXP_BASE wxString; \
+ friend class WXDLLIMPEXP_BASE wxCStrData; \
+ \
+ private: \
+ underlying_iterator m_cur
+
+ class const_iterator;
+
+#if wxUSE_UNICODE_UTF8
+ class iterator
+ {
+ // 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.
+
+ WX_STR_ITERATOR_IMPL(iterator, wxChar*, wxUniCharRef,
+ wxUniCharRef::CreateForString(m_str, m_cur));
+
+ public:
+ iterator(const iterator& i) : m_cur(i.m_cur), m_str(i.m_str) {}
+
+ iterator operator+(int n) const
+ { return iterator(m_str, wxString::AddToIter(m_cur, n)); }
+ iterator operator+(size_t n) const
+ { return iterator(m_str, wxString::AddToIter(m_cur, (int)n)); }
+ iterator operator-(int n) const
+ { return iterator(m_str, wxString::AddToIter(m_cur, -n)); }
+ iterator operator-(size_t n) const
+ { return iterator(m_str, wxString::AddToIter(m_cur, -(int)n)); }
+
+ private:
+ iterator(wxString *str, underlying_iterator ptr)
+ : m_cur(ptr), m_str(str->m_impl) {}
+ iterator(wxStringImpl& str, underlying_iterator ptr)
+ : m_cur(ptr), m_str(str) {}
+
+ wxStringImpl& m_str;
+
+ friend class const_iterator;
+ };
+#else // !wxUSE_UNICODE_UTF8
+ class iterator
+ {
+ WX_STR_ITERATOR_IMPL(iterator, wxChar*, wxUniCharRef,
+ wxUniCharRef::CreateForString(m_cur));
+
+ public:
+ iterator(const iterator& i) : m_cur(i.m_cur) {}
+
+ iterator operator+(int n) const
+ { return iterator(wxString::AddToIter(m_cur, n)); }
+ iterator operator+(size_t n) const
+ { return iterator(wxString::AddToIter(m_cur, (int)n)); }
+ iterator operator-(int n) const
+ { return iterator(wxString::AddToIter(m_cur, -n)); }
+ iterator operator-(size_t n) const
+ { return iterator(wxString::AddToIter(m_cur, -(int)n)); }
+
+ 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;
+ };
+#endif // wxUSE_UNICODE_UTF8/!wxUSE_UNICODE_UTF8
+
+ class 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,
+ wxString::DecodeChar(m_cur));
+
+ public:
+ const_iterator(const const_iterator& i) : m_cur(i.m_cur) {}
+ const_iterator(const iterator& i) : m_cur(i.m_cur) {}
+
+ const_iterator operator+(int n) const
+ { return const_iterator(wxString::AddToIter(m_cur, n)); }
+ const_iterator operator+(size_t n) const
+ { return const_iterator(wxString::AddToIter(m_cur, (int)n)); }
+ const_iterator operator-(int n) const
+ { return const_iterator(wxString::AddToIter(m_cur, -n)); }
+ const_iterator operator-(size_t n) const
+ { return const_iterator(wxString::AddToIter(m_cur, -(int)n)); }
+
+ private:
+ // for internal wxString use only:
+ const_iterator(underlying_iterator ptr) : m_cur(ptr) {}
+ };
+
+ #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;
+
+ typedef typename T::iterator_category 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(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+(int n) const
+ { return reverse_iterator_impl<T>(m_cur - n); }
+ reverse_iterator_impl operator+(size_t n) const
+ { return reverse_iterator_impl<T>(m_cur - n); }
+ reverse_iterator_impl operator-(int n) const
+ { return reverse_iterator_impl<T>(m_cur + n); }
+ reverse_iterator_impl operator-(size_t n) const
+ { return reverse_iterator_impl<T>(m_cur + n); }
+ reverse_iterator_impl operator+=(int n)
+ { m_cur -= n; return *this; }
+ reverse_iterator_impl operator+=(size_t n)
+ { m_cur -= n; return *this; }
+ reverse_iterator_impl operator-=(int n)
+ { m_cur += n; return *this; }
+ reverse_iterator_impl operator-=(size_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;