Branch data Line data Source code
1 : : // file : xsd/cxx/xml/char-utf8.txx
2 : : // copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC
3 : : // license : GNU GPL v2 + exceptions; see accompanying LICENSE file
4 : :
5 : : #include <xsd/cxx/config.hxx> // XSD_CXX11
6 : :
7 : : #ifdef XSD_CXX11
8 : : # include <memory> // std::unique_ptr
9 : : #else
10 : : # include <xsd/cxx/auto-array.hxx>
11 : : #endif
12 : :
13 : : namespace xsd
14 : : {
15 : : namespace cxx
16 : : {
17 : : namespace xml
18 : : {
19 : : template <typename C>
20 : : const unsigned char char_utf8_transcoder<C>::first_byte_mask_[5] =
21 : : {
22 : : 0x00, 0x00, 0xC0, 0xE0, 0xF0
23 : : };
24 : :
25 : : template <typename C>
26 : 16 : std::basic_string<C> char_utf8_transcoder<C>::
27 : : to (const XMLCh* s, std::size_t len)
28 : : {
29 : 16 : const XMLCh* end (s + len);
30 : :
31 : : // Find what the resulting buffer size will be.
32 : : //
33 : : std::size_t rl (0);
34 : : unsigned int u (0); // Four byte UCS-4 char.
35 : :
36 : : bool valid (true);
37 : : const XMLCh* p (s);
38 : :
39 [ + + ]: 169 : for (; p < end; ++p)
40 : : {
41 : 153 : XMLCh x (*p);
42 : :
43 [ + - ]: 153 : if (x < 0xD800 || x > 0xDBFF)
44 : 153 : u = x;
45 : : else
46 : : {
47 : : // Make sure we have one more char and it has a valid
48 : : // value for the second char in a surrogate pair.
49 : : //
50 [ # # ][ # # ]: 0 : if (++p == end || !((*p >= 0xDC00) && (*p <= 0xDFFF)))
[ # # ]
51 : : {
52 : : valid = false;
53 : : break;
54 : : }
55 : :
56 : 0 : u = ((x - 0xD800) << 10) + (*p - 0xDC00) + 0x10000;
57 : : }
58 : :
59 [ + - ]: 153 : if (u < 0x80)
60 : 153 : rl++;
61 [ # # ]: 0 : else if (u < 0x800)
62 : 0 : rl += 2;
63 [ # # ]: 0 : else if (u < 0x10000)
64 : 0 : rl += 3;
65 [ # # ]: 0 : else if (u < 0x110000)
66 : 0 : rl += 4;
67 : : else
68 : : {
69 : : valid = false;
70 : : break;
71 : : }
72 : : }
73 : :
74 [ - + ]: 16 : if (!valid)
75 : 0 : throw invalid_utf16_string ();
76 : :
77 : : std::basic_string<C> r;
78 [ + - ]: 16 : r.reserve (rl + 1);
79 : : r.resize (rl);
80 : : C* rs (const_cast<C*> (r.c_str ()));
81 : :
82 : : std::size_t i (0);
83 : : unsigned int count (0);
84 : :
85 : : p = s;
86 : :
87 : : // Tight first loop for the common case.
88 : : //
89 [ + + ][ - + ]: 169 : for (; p < end && *p < 0x80; ++p)
90 : 153 : rs[i++] = C (*p);
91 : :
92 [ - + ]: 16 : for (; p < end; ++p)
93 : : {
94 : 0 : XMLCh x (*p);
95 : :
96 [ # # ]: 0 : if ((x >= 0xD800) && (x <= 0xDBFF))
97 : : {
98 : 0 : u = ((x - 0xD800) << 10) + (*++p - 0xDC00) + 0x10000;
99 : : }
100 : : else
101 : 0 : u = x;
102 : :
103 [ # # ]: 0 : if (u < 0x80)
104 : : count = 1;
105 [ # # ]: 0 : else if (u < 0x800)
106 : : count = 2;
107 [ # # ]: 0 : else if (u < 0x10000)
108 : : count = 3;
109 [ # # ]: 0 : else if (u < 0x110000)
110 : : count = 4;
111 : :
112 [ # # # # : 0 : switch(count)
# ]
113 : : {
114 : : case 4:
115 : : {
116 : 0 : rs[i + 3] = C ((u | 0x80UL) & 0xBFUL);
117 : 0 : u >>= 6;
118 : : }
119 : : case 3:
120 : : {
121 : 0 : rs[i + 2] = C ((u | 0x80UL) & 0xBFUL);
122 : 0 : u >>= 6;
123 : : }
124 : : case 2:
125 : : {
126 : 0 : rs[i + 1] = C ((u | 0x80UL) & 0xBFUL);
127 : 0 : u >>= 6;
128 : : }
129 : : case 1:
130 : : {
131 : 0 : rs[i] = C (u | first_byte_mask_[count]);
132 : : }
133 : : }
134 : :
135 : 0 : i += count;
136 : : }
137 : :
138 : 16 : return r;
139 : : }
140 : :
141 : : template <typename C>
142 : 4 : XMLCh* char_utf8_transcoder<C>::
143 : : from (const C* s, std::size_t len)
144 : : {
145 : : bool valid (true);
146 : 4 : const C* end (s + len);
147 : :
148 : : // Find what the resulting buffer size will be.
149 : : //
150 : : std::size_t rl (0);
151 : : unsigned int count (0);
152 : :
153 [ + + ]: 88 : for (const C* p (s); p < end; ++p)
154 : : {
155 : 84 : unsigned char c (*p);
156 : :
157 [ + - ]: 84 : if (c < 0x80)
158 : : {
159 : : // Fast path.
160 : : //
161 : 84 : rl += 1;
162 : 84 : continue;
163 : : }
164 [ # # ]: 0 : else if ((c >> 5) == 0x06)
165 : : count = 2;
166 [ # # ]: 0 : else if ((c >> 4) == 0x0E)
167 : : count = 3;
168 [ # # ]: 0 : else if ((c >> 3) == 0x1E)
169 : : count = 4;
170 : : else
171 : : {
172 : : valid = false;
173 : : break;
174 : : }
175 : :
176 : 0 : p += count - 1; // One will be added in the for loop
177 : :
178 [ # # ]: 0 : if (p + 1 > end)
179 : : {
180 : : valid = false;
181 : : break;
182 : : }
183 : :
184 : : // BMP is represented by up to 3 code points in UTF-8.
185 : : //
186 [ # # ]: 0 : rl += count > 3 ? 2 : 1;
187 : : }
188 : :
189 [ - + ]: 4 : if (!valid)
190 : 0 : throw invalid_utf8_string ();
191 : :
192 : : #ifdef XSD_CXX11
193 : : std::unique_ptr<XMLCh[]> r (
194 : : #else
195 : : auto_array<XMLCh> r (
196 : : #endif
197 [ + - ]: 4 : new XMLCh[rl + 1]);
198 : : XMLCh* ir (r.get ());
199 : :
200 : : unsigned int u (0); // Four byte UCS-4 char.
201 : :
202 [ + + ]: 88 : for (const C* p (s); p < end; ++p)
203 : : {
204 : 84 : unsigned char c (*p);
205 : :
206 [ + - ]: 84 : if (c < 0x80)
207 : : {
208 : : // Fast path.
209 : : //
210 : 84 : *ir++ = static_cast<XMLCh> (c);
211 : 84 : continue;
212 : : }
213 [ # # ]: 0 : else if ((c >> 5) == 0x06)
214 : : {
215 : : // UTF-8: 110yyyyy 10zzzzzz
216 : : // Unicode: 00000yyy yyzzzzzz
217 : : //
218 : 0 : u = (c & 0x1F) << 6;
219 : :
220 : 0 : c = *++p;
221 [ # # ]: 0 : if ((c >> 6) != 2)
222 : : {
223 : : valid = false;
224 : : break;
225 : : }
226 : 0 : u |= c & 0x3F;
227 : : }
228 [ # # ]: 0 : else if ((c >> 4) == 0x0E)
229 : : {
230 : : // UTF-8: 1110xxxx 10yyyyyy 10zzzzzz
231 : : // Unicode: xxxxyyyy yyzzzzzz
232 : : //
233 : 0 : u = (c & 0x0F) << 6;
234 : :
235 : 0 : c = *++p;
236 [ # # ]: 0 : if ((c >> 6) != 2)
237 : : {
238 : : valid = false;
239 : : break;
240 : : }
241 : 0 : u = (u | (c & 0x3F)) << 6;
242 : :
243 : 0 : c = *++p;
244 [ # # ]: 0 : if ((c >> 6) != 2)
245 : : {
246 : : valid = false;
247 : : break;
248 : : }
249 : 0 : u |= c & 0x3F;
250 : : }
251 [ # # ]: 0 : else if ((c >> 3) == 0x1E)
252 : : {
253 : : // UTF-8: 000wwwxx xxxxyyyy yyzzzzzz
254 : : // Unicode: 11110www 10xxxxxx 10yyyyyy 10zzzzzz
255 : : //
256 : 0 : u = (c & 0x07) << 6;
257 : :
258 : 0 : c = *++p;
259 [ # # ]: 0 : if ((c >> 6) != 2)
260 : : {
261 : : valid = false;
262 : : break;
263 : : }
264 : 0 : u = (u | (c & 0x3F)) << 6;
265 : :
266 : 0 : c = *++p;
267 [ # # ]: 0 : if ((c >> 6) != 2)
268 : : {
269 : : valid = false;
270 : : break;
271 : : }
272 : 0 : u = (u | (c & 0x3F)) << 6;
273 : :
274 : 0 : c = *++p;
275 [ # # ]: 0 : if ((c >> 6) != 2)
276 : : {
277 : : valid = false;
278 : : break;
279 : : }
280 : 0 : u |= c & 0x3F;
281 : : }
282 : :
283 [ # # ]: 0 : if (u & 0xFFFF0000)
284 : : {
285 : : // Surrogate pair.
286 : : //
287 : 0 : *ir++ = static_cast<XMLCh> (((u - 0x10000) >> 10) + 0xD800);
288 : 0 : *ir++ = static_cast<XMLCh> ((u & 0x3FF) + 0xDC00);
289 : : }
290 : : else
291 : 0 : *ir++ = static_cast<XMLCh> (u);
292 : : }
293 : :
294 [ - + ]: 4 : if (!valid)
295 : 0 : throw invalid_utf8_string ();
296 : :
297 : 4 : *ir = XMLCh (0);
298 : :
299 : 4 : return r.release ();
300 : : }
301 : : }
302 : : }
303 : : }
|