+ : _string(src), _utf8(true)
+{
+}
+
+ustring& ustring::operator+=(const ustring& src)
+{
+ assert(_utf8 == src._utf8);
+ _string += src._string;
+ return *this;
+}
+
+ustring& ustring::operator+=(const char* src)
+{
+ _string += src;
+ return *this;
+}
+
+ustring& ustring::operator+=(char c)
+{
+ _string += c;
+ return *this;
+}
+
+ustring::size_type ustring::size() const
+{
+ if (_utf8) {
+ const char *const pdata = _string.data();
+ return utf8_ptr_to_offset(pdata, pdata + _string.size());
+ } else
+ return _string.size();
+}
+
+ustring::size_type ustring::bytes() const
+{
+ return _string.size();
+}
+
+ustring::size_type ustring::capacity() const
+{
+ return _string.capacity();
+}
+
+ustring::size_type ustring::max_size() const
+{
+ return _string.max_size();
+}
+
+bool ustring::empty() const
+{
+ return _string.empty();
+}
+
+void ustring::clear()
+{
+ _string.erase();
+}
+
+ustring& ustring::erase(ustring::size_type i, ustring::size_type n)
+{
+ if (_utf8) {
+ // find a proper offset
+ size_type utf_i = utf8_byte_offset(_string.c_str(), i);
+ if (utf_i != npos) {
+ // if the offset is not npos, find a proper length for 'n'
+ size_type utf_n = utf8_byte_offset(_string.data() + utf_i, n,
+ _string.size() - utf_i);
+ _string.erase(utf_i, utf_n);
+ }
+ } else
+ _string.erase(i, n);
+
+ return *this;
+}
+
+void ustring::resize(ustring::size_type n, char c)
+{
+ if (_utf8) {
+ const size_type size_now = size();
+ if(n < size_now)
+ erase(n, npos);
+ else if(n > size_now)
+ _string.append(n - size_now, c);
+ } else
+ _string.resize(n, c);
+}
+
+ustring::value_type ustring::operator[](ustring::size_type i) const
+{
+ return utf8_get_char(utf8_offset_to_ptr(_string.data(), i));
+}
+
+const char* ustring::data() const
+{
+ return _string.data();
+}
+
+const char* ustring::c_str() const
+{
+ return _string.c_str();
+}
+
+bool ustring::utf8() const
+{
+ return _utf8;
+}
+
+void ustring::setUtf8(bool utf8)