]> icculus.org git repositories - dana/openbox.git/blob - otk/ustring.cc
otk using ustring for shit that draws. expended its inferface yet some more.
[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 void ustring::clear()
146 {
147   _string.erase();
148 }
149
150 ustring& ustring::erase(ustring::size_type i, ustring::size_type n)
151 {
152   if (_utf8) {
153     // find a proper offset
154     size_type utf_i = utf8_byte_offset(_string.c_str(), i);
155     if (utf_i != npos) {
156       // if the offset is not npos, find a proper length for 'n'
157       size_type utf_n = utf8_byte_offset(_string.data() + utf_i, n,
158                                          _string.size() - utf_i);
159       _string.erase(utf_i, utf_n);
160     }
161   } else
162     _string.erase(i, n);
163
164   return *this;
165 }
166
167 void ustring::resize(ustring::size_type n, char c)
168 {
169   if (_utf8) {
170     const size_type size_now = size();
171     if(n < size_now)
172       erase(n, npos);
173     else if(n > size_now)
174       _string.append(n - size_now, c);
175   } else
176     _string.resize(n, c);
177 }
178
179 const char* ustring::data() const
180 {
181   return _string.data();
182 }
183
184 const char* ustring::c_str() const
185 {
186   return _string.c_str();
187 }
188
189 bool ustring::utf8() const
190 {
191   return _utf8;
192 }
193
194 void ustring::setUtf8(bool utf8)
195 {
196   _utf8 = utf8;
197 }
198
199 }