almost done the ustring conversion
[dana/openbox.git] / otk / ustring.cc
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2
3 #ifdef    HAVE_CONFIG_H
4 #  include "../config.h"
5 #endif // HAVE_CONFIG_H
6
7 #include "ustring.hh"
8
9 extern "C" {
10 #include <assert.h>
11 }
12
13 namespace otk {
14
15 // helper functions
16
17 static ustring::size_type utf8_find_offset(const char *str, const char *pos)
18 {
19   ustring::size_type offset = 0;
20
21   while (str < pos) {
22     str += g_utf8_skip[*str];
23     offset += g_utf8_skip[*str];
24   }
25
26   return offset;
27 }
28
29 // First overload: stop on '\0' character.
30 ustring::size_type utf8_byte_offset(const char* str, ustring::size_type offset)
31 {
32   if(offset == ustring::npos)
33     return ustring::npos;
34
35   const char* p = str;
36
37   for(; offset != 0; --offset)
38   {
39     if(*p == '\0')
40       return ustring::npos;
41
42     p += g_utf8_skip[*p];
43   }
44
45   return (p - str);
46 }
47
48 // Second overload: stop when reaching maxlen.
49 ustring::size_type utf8_byte_offset(const char* str, ustring::size_type offset,
50                                     ustring::size_type maxlen)
51 {
52   if(offset == ustring::npos)
53     return ustring::npos;
54
55   const char *const pend = str + maxlen;
56   const char* p = str;
57
58   for(; offset != 0; --offset)
59   {
60     if(p >= pend)
61       return ustring::npos;
62
63     p += g_utf8_skip[*p];
64   }
65
66   return (p - str);
67 }
68
69
70 // ustring methods
71
72 ustring::ustring()
73 {
74 }
75
76 ustring::~ustring()
77 {
78 }
79
80 ustring::ustring(const ustring& other)
81   : _string(other._string), _utf8(other._utf8)
82 {
83 }
84
85 ustring& ustring::operator=(const ustring& other)
86 {
87   _string = other._string;
88   _utf8 = other._utf8;
89   return *this;
90 }
91
92 ustring::ustring(const std::string& src)
93   : _string(src), _utf8(true)
94 {
95 }
96
97 ustring::ustring(const char* src)
98   : _string(src), _utf8(true)
99 {
100 }
101
102 ustring& ustring::operator+=(const ustring& src)
103 {
104   assert(_utf8 == src._utf8);
105   _string += src._string;
106   return *this;
107 }
108
109 ustring& ustring::operator+=(const char* src)
110 {
111   _string += src;
112   return *this;
113 }
114
115 ustring& ustring::operator+=(char c)
116 {
117   _string += c;
118   return *this;
119 }
120
121 ustring::size_type ustring::size() const
122 {
123   if (_utf8) {
124     const char *const pdata = _string.data();
125     return utf8_find_offset(pdata, pdata + _string.size());
126   } else
127     return _string.size();
128 }
129
130 ustring::size_type ustring::bytes() const
131 {
132   return _string.size();
133 }
134
135 ustring::size_type ustring::capacity() const
136 {
137   return _string.capacity();
138 }
139
140 ustring::size_type ustring::max_size() const
141 {
142   return _string.max_size();
143 }
144
145 bool ustring::empty() const
146 {
147   return _string.empty();
148 }
149
150 void ustring::clear()
151 {
152   _string.erase();
153 }
154
155 ustring& ustring::erase(ustring::size_type i, ustring::size_type n)
156 {
157   if (_utf8) {
158     // find a proper offset
159     size_type utf_i = utf8_byte_offset(_string.c_str(), i);
160     if (utf_i != npos) {
161       // if the offset is not npos, find a proper length for 'n'
162       size_type utf_n = utf8_byte_offset(_string.data() + utf_i, n,
163                                          _string.size() - utf_i);
164       _string.erase(utf_i, utf_n);
165     }
166   } else
167     _string.erase(i, n);
168
169   return *this;
170 }
171
172 void ustring::resize(ustring::size_type n, char c)
173 {
174   if (_utf8) {
175     const size_type size_now = size();
176     if(n < size_now)
177       erase(n, npos);
178     else if(n > size_now)
179       _string.append(n - size_now, c);
180   } else
181     _string.resize(n, c);
182 }
183
184 const char* ustring::data() const
185 {
186   return _string.data();
187 }
188
189 const char* ustring::c_str() const
190 {
191   return _string.c_str();
192 }
193
194 bool ustring::utf8() const
195 {
196   return _utf8;
197 }
198
199 void ustring::setUtf8(bool utf8)
200 {
201   _utf8 = utf8;
202 }
203
204 }