00001
00002
00003 #ifdef HAVE_CONFIG_H
00004 # include "../config.h"
00005 #endif // HAVE_CONFIG_H
00006
00007 #include "ustring.hh"
00008
00009 extern "C" {
00010 #include <assert.h>
00011 }
00012
00013 namespace otk {
00014
00015
00016
00017
00018 static const char utf8_skip[256] = {
00019 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
00020 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
00021 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
00022 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
00023 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
00024 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
00025 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
00026 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1
00027 };
00028
00029
00030
00031 unichar utf8_get_char (const char *p)
00032 {
00033 unichar result = static_cast<unsigned char>(*p);
00034
00035
00036 if((result & 0x80) != 0) {
00037
00038 unsigned char len = utf8_skip[result];
00039 result &= 0x7F >> len;
00040
00041 while(--len != 0) {
00042 result <<= 6;
00043 result |= static_cast<unsigned char>(*++p) & 0x3F;
00044 }
00045 }
00046
00047 return result;
00048 }
00049
00050
00051 static ustring::size_type utf8_ptr_to_offset(const char *str, const char *pos)
00052 {
00053 ustring::size_type offset = 0;
00054
00055 while (str < pos) {
00056 str += utf8_skip[static_cast<unsigned char>(*str)];
00057 offset++;
00058 }
00059
00060 return offset;
00061 }
00062
00063
00064 const char *utf8_offset_to_ptr(const char *str, ustring::size_type offset)
00065 {
00066 while (offset--)
00067 str += utf8_skip[static_cast<unsigned char>(*str)];
00068 return str;
00069 }
00070
00071
00072 ustring::size_type utf8_byte_offset(const char* str, ustring::size_type offset)
00073 {
00074 if(offset == ustring::npos)
00075 return ustring::npos;
00076
00077 const char* p = str;
00078
00079 for(; offset != 0; --offset)
00080 {
00081 if(*p == '\0')
00082 return ustring::npos;
00083
00084 p += utf8_skip[static_cast<unsigned char>(*p)];
00085 }
00086
00087 return (p - str);
00088 }
00089
00090
00091 ustring::size_type utf8_byte_offset(const char* str, ustring::size_type offset,
00092 ustring::size_type maxlen)
00093 {
00094 if(offset == ustring::npos)
00095 return ustring::npos;
00096
00097 const char *const pend = str + maxlen;
00098 const char* p = str;
00099
00100 for(; offset != 0; --offset)
00101 {
00102 if(p >= pend)
00103 return ustring::npos;
00104
00105 p += utf8_skip[static_cast<unsigned char>(*p)];
00106 }
00107
00108 return (p - str);
00109 }
00110
00111
00112
00113
00114 ustring::ustring(bool utf8)
00115 : _utf8(utf8)
00116 {
00117 }
00118
00119 ustring::~ustring()
00120 {
00121 }
00122
00123 ustring::ustring(const ustring& other)
00124 : _string(other._string), _utf8(other._utf8)
00125 {
00126 }
00127
00128 ustring& ustring::operator=(const ustring& other)
00129 {
00130 _string = other._string;
00131 _utf8 = other._utf8;
00132 return *this;
00133 }
00134
00135 ustring::ustring(const std::string& src, bool utf8)
00136 : _string(src), _utf8(utf8)
00137 {
00138 }
00139
00140 ustring::ustring(const char* src, bool utf8)
00141 : _string(src), _utf8(utf8)
00142 {
00143 }
00144
00145 ustring& ustring::operator+=(const ustring& src)
00146 {
00147 assert(_utf8 == src._utf8);
00148 _string += src._string;
00149 return *this;
00150 }
00151
00152 ustring& ustring::operator+=(const char* src)
00153 {
00154 _string += src;
00155 return *this;
00156 }
00157
00158 ustring& ustring::operator+=(char c)
00159 {
00160 _string += c;
00161 return *this;
00162 }
00163
00164 ustring::size_type ustring::size() const
00165 {
00166 if (_utf8) {
00167 const char *const pdata = _string.data();
00168 return utf8_ptr_to_offset(pdata, pdata + _string.size());
00169 } else
00170 return _string.size();
00171 }
00172
00173 ustring::size_type ustring::bytes() const
00174 {
00175 return _string.size();
00176 }
00177
00178 ustring::size_type ustring::capacity() const
00179 {
00180 return _string.capacity();
00181 }
00182
00183 ustring::size_type ustring::max_size() const
00184 {
00185 return _string.max_size();
00186 }
00187
00188 bool ustring::empty() const
00189 {
00190 return _string.empty();
00191 }
00192
00193 void ustring::clear()
00194 {
00195 _string.erase();
00196 }
00197
00198 ustring& ustring::erase(ustring::size_type i, ustring::size_type n)
00199 {
00200 if (_utf8) {
00201
00202 size_type utf_i = utf8_byte_offset(_string.c_str(), i);
00203 if (utf_i != npos) {
00204
00205 size_type utf_n = utf8_byte_offset(_string.data() + utf_i, n,
00206 _string.size() - utf_i);
00207 _string.erase(utf_i, utf_n);
00208 }
00209 } else
00210 _string.erase(i, n);
00211
00212 return *this;
00213 }
00214
00215 void ustring::resize(ustring::size_type n, char c)
00216 {
00217 if (_utf8) {
00218 const size_type size_now = size();
00219 if(n < size_now)
00220 erase(n, npos);
00221 else if(n > size_now)
00222 _string.append(n - size_now, c);
00223 } else
00224 _string.resize(n, c);
00225 }
00226
00227 ustring::value_type ustring::operator[](ustring::size_type i) const
00228 {
00229 return utf8_get_char(utf8_offset_to_ptr(_string.data(), i));
00230 }
00231
00232 bool ustring::operator==(const ustring &other) const
00233 {
00234 return _string == other._string && _utf8 == other._utf8;
00235 }
00236
00237 bool ustring::operator==(const std::string &other) const
00238 {
00239 return _string == other;
00240 }
00241
00242 bool ustring::operator==(const char *other) const
00243 {
00244 return _string == other;
00245 }
00246
00247 const char* ustring::data() const
00248 {
00249 return _string.data();
00250 }
00251
00252 const char* ustring::c_str() const
00253 {
00254 return _string.c_str();
00255 }
00256
00257 bool ustring::utf8() const
00258 {
00259 return _utf8;
00260 }
00261
00262 void ustring::setUtf8(bool utf8)
00263 {
00264 _utf8 = utf8;
00265 }
00266
00267 }