Crevice  0.1
 All Classes Functions Variables Pages
Ustring.cc
1 /*
2  * File: Unicode.cc
3  *
4  * Copyright 2014 Heinrich Schuchardt <xypron.glpk@gmx.de>
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #include "Ustring.h"
20 #include <iostream>
21 
27 int Ustring::getchar(std::istream *ifs) {
28  int ret = ifs->get();
29  if (!ifs->good()) {
30  Ustring::Eof eof;
31  throw eof;
32  }
33  return ret;
34 }
35 
40 }
41 
47 Ustring::Ustring(std::istream *ifs) {
48  try {
49  int i;
50  i = getchar(ifs);
51 
52  for (;;) {
53  Uchar u;
54 
55  if (0 == (i & 0x80)) {
56  u = i;
57  } else if (0xC0 == (i & 0xE0)) {
58  u = i & 0x1F;
59 
60  // Get next 6 bits
61  i = getchar(ifs);
62  if (0x80 != (i & 0xC0)) {
63  throw invalid;
64  }
65  i &= 0x3F;
66  u <<= 6;
67  u += i;
68  } else if (0xE0 == (i & 0xF0)) {
69  u = i & 0x0F;
70 
71  // Get next 6 bits
72  i = getchar(ifs);
73  if (0x80 != (i & 0xC0)) {
74  throw invalid;
75  }
76  i &= 0x3F;
77  u <<= 6;
78  u += i;
79  // Get next 6 bits
80  i = getchar(ifs);
81  if (0x80 != (i & 0xC0)) {
82  throw invalid;
83  }
84  i &= 0x3F;
85  u <<= 6;
86  u += i;
87  } else if (0xF0 == (i & 0xF8)) {
88  u = i & 0x07;
89 
90  // Get next 6 bits
91  i = getchar(ifs);
92  if (0x80 != (i & 0xC0)) {
93  throw invalid;
94  }
95  i &= 0x3F;
96  u <<= 6;
97  u += i;
98  // Get next 6 bits
99  i = getchar(ifs);
100  if (0x80 != (i & 0xC0)) {
101  throw invalid;
102  }
103  i &= 0x3F;
104  u <<= 6;
105  u += i;
106  // Get next 6 bits
107  i = getchar(ifs);
108  if (0x80 != (i & 0xC0)) {
109  throw invalid;
110  }
111  i &= 0x3F;
112  u <<= 6;
113  u += i;
114  } else {
115  throw invalid;
116  }
117  // Append unicode character if it is not a byte order mark.
118  switch (u) {
119  case BYTE_ORDER_MARK:
120  break;
121  default:
122  s.push_back(u);
123  }
124  // Get next byte.
125  i = getchar(ifs);
126  }
127  } catch (const Invalid &e) {
128  std::cerr << "Ustring::Ustring(std::istream): "
129  "Stream is not valid utf8" << std::endl;
130  throw e;
131  } catch (const Eof &e) {
132  }
133 }
134 
139 Ustring::Ustring(const Ustring &orig) {
140  for (std::vector<Uchar>::const_iterator it = orig.s.begin();
141  it != orig.s.end(); ++it) {
142  s.push_back(*it);
143  }
144 }
145 
150 }
151 
156 std::vector<Uchar>::const_iterator Ustring::begin() {
157  return s.begin();
158 };
159 
164 std::vector<Uchar>::const_iterator Ustring::end() {
165  return s.end();
166 };
167 
173  return s.size();
174 };
175 
176 const bool Ustring::operator==(const char *right) const {
177  int i;
178  for (i = 0; right[i]; ++i) {
179  if (i >= s.size()) {
180  return false;
181  }
182  if (s[i] != right[i]) {
183  return false;
184  }
185  }
186  if (i < s.size()) {
187  return false;
188  }
189  return true;
190 }
191 
192 Ustring* Ustring::operator+=(const Uchar &right) {
193  if (right < 0x1FFFFFu) {
194  s.push_back(right);
195  } else {
196  throw invalid;
197  }
198  return this;
199 }
200 
201 Ustring* Ustring::operator+=(const char *right) {
202  for (const char *pos = right; *pos; ++pos) {
203  if (*pos >= 0 && *pos <= 127) {
204  s.push_back((Uchar) * pos);
205  } else {
206  throw invalid;
207  }
208  }
209  return this;
210 }
211 
212 std::string* Ustring::operator>>(std::string &str) {
213  for (int i = 0; i < s.size(); ++i) {
214  Uchar u = s[i];
215  char c[5];
216  if (u < 0x80) {
217  c[0] = u & 0x7F;
218  c[1] = 0;
219  str.append(c);
220  } else if (u < 0x800) {
221  c[1] = 0x80 | (u & 0x3F);
222  u >>= 6;
223  c[0] = 0xC0 | (u & 0x1F);
224  c[2] = 0;
225  str.append(c);
226  } else if (u < 0x10000) {
227  c[2] = 0x80 | (u & 0x3F);
228  u >>= 6;
229  c[1] = 0x80 | (u & 0x3F);
230  u >>= 6;
231  c[0] = 0xE0 | (u & 0x0F);
232  c[3] = 0;
233  str.append(c);
234  } else if (u < 0x200000) {
235  c[3] = 0x80 | (u & 0x3F);
236  u >>= 6;
237  c[2] = 0x80 | (u & 0x3F);
238  u >>= 6;
239  c[1] = 0x80 | (u & 0x3F);
240  u >>= 6;
241  c[0] = 0xF0 | (u & 0x07);
242  c[4] = 0;
243  str.append(c);
244  } else {
245  throw invalid;
246  }
247  }
248  return &str;
249 }
250 
251 const bool Ustring::operator<(const Ustring &right) const {
252  int i;
253  for (i = 0;; ++i) {
254  Uchar c;
255  try {
256  c = right.charAt(i);
257  } catch (const Invalid &e) {
258  break;
259  }
260  if (i >= s.size()) {
261  // Right string is longer.
262  return true;
263  }
264  if (s[i] < c) {
265  // Left character is less then right character.
266  return true;
267  }
268  }
269  // Both strings are equal or left string is longer.
270  return false;
271 }
272 
278 const Uchar & Ustring::charAt(int pos) const {
279  if (pos < 0 || pos >= s.size()) {
280  throw invalid;
281  } else {
282  return s[pos];
283  }
284 }
285