Branch data Line data Source code
1 : : /* stringlib: codec implementations */
2 : :
3 : : #if !STRINGLIB_IS_UNICODE
4 : : # error "codecs.h is specific to Unicode"
5 : : #endif
6 : :
7 : : #include "pycore_bitutils.h" // _Py_bswap32()
8 : :
9 : : /* Mask to quickly check whether a C 'size_t' contains a
10 : : non-ASCII, UTF8-encoded char. */
11 : : #if (SIZEOF_SIZE_T == 8)
12 : : # define ASCII_CHAR_MASK 0x8080808080808080ULL
13 : : #elif (SIZEOF_SIZE_T == 4)
14 : : # define ASCII_CHAR_MASK 0x80808080U
15 : : #else
16 : : # error C 'size_t' size should be either 4 or 8!
17 : : #endif
18 : :
19 : : /* 10xxxxxx */
20 : : #define IS_CONTINUATION_BYTE(ch) ((ch) >= 0x80 && (ch) < 0xC0)
21 : :
22 : : Py_LOCAL_INLINE(Py_UCS4)
23 : 803548 : STRINGLIB(utf8_decode)(const char **inptr, const char *end,
24 : : STRINGLIB_CHAR *dest,
25 : : Py_ssize_t *outpos)
26 : : {
27 : : Py_UCS4 ch;
28 : 803548 : const char *s = *inptr;
29 : 803548 : STRINGLIB_CHAR *p = dest + *outpos;
30 : :
31 [ + + ]: 4648890 : while (s < end) {
32 : 4447512 : ch = (unsigned char)*s;
33 : :
34 [ + + ]: 4447512 : if (ch < 0x80) {
35 : : /* Fast path for runs of ASCII characters. Given that common UTF-8
36 : : input will consist of an overwhelming majority of ASCII
37 : : characters, we try to optimize for this case by checking
38 : : as many characters as a C 'size_t' can contain.
39 : : First, check if we can do an aligned read, as most CPUs have
40 : : a penalty for unaligned reads.
41 : : */
42 [ + + ]: 1667846 : if (_Py_IS_ALIGNED(s, ALIGNOF_SIZE_T)) {
43 : : /* Help register allocation */
44 : 193595 : const char *_s = s;
45 : 193595 : STRINGLIB_CHAR *_p = p;
46 [ + + ]: 3387426 : while (_s + SIZEOF_SIZE_T <= end) {
47 : : /* Read a whole size_t at a time (either 4 or 8 bytes),
48 : : and do a fast unrolled copy if it only contains ASCII
49 : : characters. */
50 : 3279613 : size_t value = *(const size_t *) _s;
51 [ + + ]: 3279613 : if (value & ASCII_CHAR_MASK)
52 : 85782 : break;
53 : : #if PY_LITTLE_ENDIAN
54 : 3193831 : _p[0] = (STRINGLIB_CHAR)(value & 0xFFu);
55 : 3193831 : _p[1] = (STRINGLIB_CHAR)((value >> 8) & 0xFFu);
56 : 3193831 : _p[2] = (STRINGLIB_CHAR)((value >> 16) & 0xFFu);
57 : 3193831 : _p[3] = (STRINGLIB_CHAR)((value >> 24) & 0xFFu);
58 : : # if SIZEOF_SIZE_T == 8
59 : 3193831 : _p[4] = (STRINGLIB_CHAR)((value >> 32) & 0xFFu);
60 : 3193831 : _p[5] = (STRINGLIB_CHAR)((value >> 40) & 0xFFu);
61 : 3193831 : _p[6] = (STRINGLIB_CHAR)((value >> 48) & 0xFFu);
62 : 3193831 : _p[7] = (STRINGLIB_CHAR)((value >> 56) & 0xFFu);
63 : : # endif
64 : : #else
65 : : # if SIZEOF_SIZE_T == 8
66 : : _p[0] = (STRINGLIB_CHAR)((value >> 56) & 0xFFu);
67 : : _p[1] = (STRINGLIB_CHAR)((value >> 48) & 0xFFu);
68 : : _p[2] = (STRINGLIB_CHAR)((value >> 40) & 0xFFu);
69 : : _p[3] = (STRINGLIB_CHAR)((value >> 32) & 0xFFu);
70 : : _p[4] = (STRINGLIB_CHAR)((value >> 24) & 0xFFu);
71 : : _p[5] = (STRINGLIB_CHAR)((value >> 16) & 0xFFu);
72 : : _p[6] = (STRINGLIB_CHAR)((value >> 8) & 0xFFu);
73 : : _p[7] = (STRINGLIB_CHAR)(value & 0xFFu);
74 : : # else
75 : : _p[0] = (STRINGLIB_CHAR)((value >> 24) & 0xFFu);
76 : : _p[1] = (STRINGLIB_CHAR)((value >> 16) & 0xFFu);
77 : : _p[2] = (STRINGLIB_CHAR)((value >> 8) & 0xFFu);
78 : : _p[3] = (STRINGLIB_CHAR)(value & 0xFFu);
79 : : # endif
80 : : #endif
81 : 3193831 : _s += SIZEOF_SIZE_T;
82 : 3193831 : _p += SIZEOF_SIZE_T;
83 : : }
84 : 193595 : s = _s;
85 : 193595 : p = _p;
86 [ + + ]: 193595 : if (s == end)
87 : 8097 : break;
88 : 185498 : ch = (unsigned char)*s;
89 : : }
90 [ + + ]: 1659749 : if (ch < 0x80) {
91 : 1643515 : s++;
92 : 1643515 : *p++ = ch;
93 : 1643515 : continue;
94 : : }
95 : : }
96 : :
97 [ + + ]: 2795900 : if (ch < 0xE0) {
98 : : /* \xC2\x80-\xDF\xBF -- 0080-07FF */
99 : : Py_UCS4 ch2;
100 [ + + ]: 387820 : if (ch < 0xC2) {
101 : : /* invalid sequence
102 : : \x80-\xBF -- continuation byte
103 : : \xC0-\xC1 -- fake 0000-007F */
104 : 971 : goto InvalidStart;
105 : : }
106 [ + + ]: 386849 : if (end - s < 2) {
107 : : /* unexpected end of data: the caller will decide whether
108 : : it's an error or not */
109 : 2217 : break;
110 : : }
111 : 384632 : ch2 = (unsigned char)s[1];
112 [ + + + + ]: 384632 : if (!IS_CONTINUATION_BYTE(ch2))
113 : : /* invalid continuation byte */
114 : 1106 : goto InvalidContinuation1;
115 : 383526 : ch = (ch << 6) + ch2 -
116 : : ((0xC0 << 6) + 0x80);
117 : : assert ((ch > 0x007F) && (ch <= 0x07FF));
118 : 383526 : s += 2;
119 [ + + ]: 147729 : if (STRINGLIB_MAX_CHAR <= 0x007F ||
120 : : (STRINGLIB_MAX_CHAR < 0x07FF && ch > STRINGLIB_MAX_CHAR))
121 : : /* Out-of-range */
122 : 139759 : goto Return;
123 : 243767 : *p++ = ch;
124 : 243767 : continue;
125 : : }
126 : :
127 [ + + ]: 2408080 : if (ch < 0xF0) {
128 : : /* \xE0\xA0\x80-\xEF\xBF\xBF -- 0800-FFFF */
129 : : Py_UCS4 ch2, ch3;
130 [ + + ]: 1249090 : if (end - s < 3) {
131 : : /* unexpected end of data: the caller will decide whether
132 : : it's an error or not */
133 [ + + ]: 119993 : if (end - s < 2)
134 : 58166 : break;
135 : 61827 : ch2 = (unsigned char)s[1];
136 [ + + + + : 61827 : if (!IS_CONTINUATION_BYTE(ch2) ||
+ + + + +
+ ]
137 : : (ch2 < 0xA0 ? ch == 0xE0 : ch == 0xED))
138 : : /* for clarification see comments below */
139 : 119 : goto InvalidContinuation1;
140 : 61708 : break;
141 : : }
142 : 1129097 : ch2 = (unsigned char)s[1];
143 : 1129097 : ch3 = (unsigned char)s[2];
144 [ + + + + ]: 1129097 : if (!IS_CONTINUATION_BYTE(ch2)) {
145 : : /* invalid continuation byte */
146 : 7951 : goto InvalidContinuation1;
147 : : }
148 [ + + ]: 1121146 : if (ch == 0xE0) {
149 [ + + ]: 20917 : if (ch2 < 0xA0)
150 : : /* invalid sequence
151 : : \xE0\x80\x80-\xE0\x9F\xBF -- fake 0000-0800 */
152 : 68 : goto InvalidContinuation1;
153 [ + + + + ]: 1100229 : } else if (ch == 0xED && ch2 >= 0xA0) {
154 : : /* Decoding UTF-8 sequences in range \xED\xA0\x80-\xED\xBF\xBF
155 : : will result in surrogates in range D800-DFFF. Surrogates are
156 : : not valid UTF-8 so they are rejected.
157 : : See https://www.unicode.org/versions/Unicode5.2.0/ch03.pdf
158 : : (table 3-7) and http://www.rfc-editor.org/rfc/rfc3629.txt */
159 : 1395 : goto InvalidContinuation1;
160 : : }
161 [ + + + + ]: 1119683 : if (!IS_CONTINUATION_BYTE(ch3)) {
162 : : /* invalid continuation byte */
163 : 288 : goto InvalidContinuation2;
164 : : }
165 : 1119395 : ch = (ch << 12) + (ch2 << 6) + ch3 -
166 : : ((0xE0 << 12) + (0x80 << 6) + 0x80);
167 : : assert ((ch > 0x07FF) && (ch <= 0xFFFF));
168 : 1119395 : s += 3;
169 : : if (STRINGLIB_MAX_CHAR <= 0x07FF ||
170 : : (STRINGLIB_MAX_CHAR < 0xFFFF && ch > STRINGLIB_MAX_CHAR))
171 : : /* Out-of-range */
172 : 245269 : goto Return;
173 : 874126 : *p++ = ch;
174 : 874126 : continue;
175 : : }
176 : :
177 [ + + ]: 1158990 : if (ch < 0xF5) {
178 : : /* \xF0\x90\x80\x80-\xF4\x8F\xBF\xBF -- 10000-10FFFF */
179 : : Py_UCS4 ch2, ch3, ch4;
180 [ + + ]: 1155037 : if (end - s < 4) {
181 : : /* unexpected end of data: the caller will decide whether
182 : : it's an error or not */
183 [ + + ]: 6568 : if (end - s < 2)
184 : 6052 : break;
185 : 516 : ch2 = (unsigned char)s[1];
186 [ + + + + : 516 : if (!IS_CONTINUATION_BYTE(ch2) ||
+ + + + +
+ ]
187 : : (ch2 < 0x90 ? ch == 0xF0 : ch == 0xF4))
188 : : /* for clarification see comments below */
189 : 127 : goto InvalidContinuation1;
190 [ + + ]: 389 : if (end - s < 3)
191 : 125 : break;
192 : 264 : ch3 = (unsigned char)s[2];
193 [ + + + + ]: 264 : if (!IS_CONTINUATION_BYTE(ch3))
194 : 111 : goto InvalidContinuation2;
195 : 153 : break;
196 : : }
197 : 1148469 : ch2 = (unsigned char)s[1];
198 : 1148469 : ch3 = (unsigned char)s[2];
199 : 1148469 : ch4 = (unsigned char)s[3];
200 [ + + + + ]: 1148469 : if (!IS_CONTINUATION_BYTE(ch2)) {
201 : : /* invalid continuation byte */
202 : 94 : goto InvalidContinuation1;
203 : : }
204 [ + + ]: 1148375 : if (ch == 0xF0) {
205 [ + + ]: 295621 : if (ch2 < 0x90)
206 : : /* invalid sequence
207 : : \xF0\x80\x80\x80-\xF0\x8F\xBF\xBF -- fake 0000-FFFF */
208 : 36 : goto InvalidContinuation1;
209 [ + + + + ]: 852754 : } else if (ch == 0xF4 && ch2 >= 0x90) {
210 : : /* invalid sequence
211 : : \xF4\x90\x80\x80- -- 110000- overflow */
212 : 100 : goto InvalidContinuation1;
213 : : }
214 [ + + + + ]: 1148239 : if (!IS_CONTINUATION_BYTE(ch3)) {
215 : : /* invalid continuation byte */
216 : 98 : goto InvalidContinuation2;
217 : : }
218 [ + + + + ]: 1148141 : if (!IS_CONTINUATION_BYTE(ch4)) {
219 : : /* invalid continuation byte */
220 : 369 : goto InvalidContinuation3;
221 : : }
222 : 1147772 : ch = (ch << 18) + (ch2 << 12) + (ch3 << 6) + ch4 -
223 : : ((0xF0 << 18) + (0x80 << 12) + (0x80 << 6) + 0x80);
224 : : assert ((ch > 0xFFFF) && (ch <= 0x10FFFF));
225 : 1147772 : s += 4;
226 : : if (STRINGLIB_MAX_CHAR <= 0xFFFF ||
227 : : (STRINGLIB_MAX_CHAR < 0x10FFFF && ch > STRINGLIB_MAX_CHAR))
228 : : /* Out-of-range */
229 : 63838 : goto Return;
230 : 1083934 : *p++ = ch;
231 : 1083934 : continue;
232 : : }
233 : 3953 : goto InvalidStart;
234 : : }
235 : 337896 : ch = 0;
236 : 803548 : Return:
237 : 803548 : *inptr = s;
238 : 803548 : *outpos = p - dest;
239 : 803548 : return ch;
240 : 4924 : InvalidStart:
241 : 4924 : ch = 1;
242 : 4924 : goto Return;
243 : 10996 : InvalidContinuation1:
244 : 10996 : ch = 2;
245 : 10996 : goto Return;
246 : 497 : InvalidContinuation2:
247 : 497 : ch = 3;
248 : 497 : goto Return;
249 : 369 : InvalidContinuation3:
250 : 369 : ch = 4;
251 : 369 : goto Return;
252 : : }
253 : :
254 : : #undef ASCII_CHAR_MASK
255 : :
256 : :
257 : : /* UTF-8 encoder specialized for a Unicode kind to avoid the slow
258 : : PyUnicode_READ() macro. Delete some parts of the code depending on the kind:
259 : : UCS-1 strings don't need to handle surrogates for example. */
260 : : Py_LOCAL_INLINE(char *)
261 : 1499776 : STRINGLIB(utf8_encoder)(_PyBytesWriter *writer,
262 : : PyObject *unicode,
263 : : const STRINGLIB_CHAR *data,
264 : : Py_ssize_t size,
265 : : _Py_error_handler error_handler,
266 : : const char *errors)
267 : : {
268 : : Py_ssize_t i; /* index into data of next input character */
269 : : char *p; /* next free byte in output buffer */
270 : : #if STRINGLIB_SIZEOF_CHAR > 1
271 : 1311389 : PyObject *error_handler_obj = NULL;
272 : 1311389 : PyObject *exc = NULL;
273 : 1311389 : PyObject *rep = NULL;
274 : : #endif
275 : : #if STRINGLIB_SIZEOF_CHAR == 1
276 : 188387 : const Py_ssize_t max_char_size = 2;
277 : : #elif STRINGLIB_SIZEOF_CHAR == 2
278 : 247813 : const Py_ssize_t max_char_size = 3;
279 : : #else /* STRINGLIB_SIZEOF_CHAR == 4 */
280 : 1063576 : const Py_ssize_t max_char_size = 4;
281 : : #endif
282 : :
283 : : assert(size >= 0);
284 [ - + ]: 1499776 : if (size > PY_SSIZE_T_MAX / max_char_size) {
285 : : /* integer overflow */
286 : : PyErr_NoMemory();
287 : 0 : return NULL;
288 : : }
289 : :
290 : 1499776 : _PyBytesWriter_Init(writer);
291 : 1499776 : p = _PyBytesWriter_Alloc(writer, size * max_char_size);
292 [ - + ]: 1499776 : if (p == NULL)
293 : 0 : return NULL;
294 : :
295 [ + + ]: 106510811 : for (i = 0; i < size;) {
296 : 105011417 : Py_UCS4 ch = data[i++];
297 : :
298 [ + + ]: 105011417 : if (ch < 0x80) {
299 : : /* Encode ASCII */
300 : 94798054 : *p++ = (char) ch;
301 : :
302 : : }
303 : : else
304 : : #if STRINGLIB_SIZEOF_CHAR > 1
305 [ + + ]: 9837889 : if (ch < 0x0800)
306 : : #endif
307 : : {
308 : : /* Encode Latin-1 */
309 : 452713 : *p++ = (char)(0xc0 | (ch >> 6));
310 : 452713 : *p++ = (char)(0x80 | (ch & 0x3f));
311 : : }
312 : : #if STRINGLIB_SIZEOF_CHAR > 1
313 [ + + ]: 9760650 : else if (Py_UNICODE_IS_SURROGATE(ch)) {
314 : : Py_ssize_t startpos, endpos, newpos;
315 : : Py_ssize_t k;
316 [ + + ]: 13049 : if (error_handler == _Py_ERROR_UNKNOWN) {
317 : 4427 : error_handler = _Py_GetErrorHandler(errors);
318 : : }
319 : :
320 : 13049 : startpos = i-1;
321 : 13049 : endpos = startpos+1;
322 : :
323 [ + + + + ]: 19836 : while ((endpos < size) && Py_UNICODE_IS_SURROGATE(data[endpos]))
324 : 6787 : endpos++;
325 : :
326 : : /* Only overallocate the buffer if it's not the last write */
327 : 13049 : writer->overallocate = (endpos < size);
328 : :
329 [ + + + + : 13049 : switch (error_handler)
+ + + ]
330 : : {
331 : 4 : case _Py_ERROR_REPLACE:
332 : 4 : memset(p, '?', endpos - startpos);
333 : 4 : p += (endpos - startpos);
334 : : /* fall through */
335 : 8 : case _Py_ERROR_IGNORE:
336 : 8 : i += (endpos - startpos - 1);
337 : 8 : break;
338 : :
339 : 8448 : case _Py_ERROR_SURROGATEPASS:
340 [ + + ]: 23218 : for (k=startpos; k<endpos; k++) {
341 : 14770 : ch = data[k];
342 : 14770 : *p++ = (char)(0xe0 | (ch >> 12));
343 : 14770 : *p++ = (char)(0x80 | ((ch >> 6) & 0x3f));
344 : 14770 : *p++ = (char)(0x80 | (ch & 0x3f));
345 : : }
346 : 8448 : i += (endpos - startpos - 1);
347 : 8448 : break;
348 : :
349 : 5 : case _Py_ERROR_BACKSLASHREPLACE:
350 : : /* subtract preallocated bytes */
351 : 5 : writer->min_size -= max_char_size * (endpos - startpos);
352 : 5 : p = backslashreplace(writer, p,
353 : : unicode, startpos, endpos);
354 [ - + ]: 5 : if (p == NULL)
355 : 382 : goto error;
356 : 5 : i += (endpos - startpos - 1);
357 : 5 : break;
358 : :
359 : 2 : case _Py_ERROR_XMLCHARREFREPLACE:
360 : : /* subtract preallocated bytes */
361 : 2 : writer->min_size -= max_char_size * (endpos - startpos);
362 : 2 : p = xmlcharrefreplace(writer, p,
363 : : unicode, startpos, endpos);
364 [ - + ]: 2 : if (p == NULL)
365 : 0 : goto error;
366 : 2 : i += (endpos - startpos - 1);
367 : 2 : break;
368 : :
369 : 4204 : case _Py_ERROR_SURROGATEESCAPE:
370 [ + + ]: 8444 : for (k=startpos; k<endpos; k++) {
371 : 4294 : ch = data[k];
372 [ + + + + ]: 4294 : if (!(0xDC80 <= ch && ch <= 0xDCFF))
373 : : break;
374 : 4240 : *p++ = (char)(ch & 0xff);
375 : : }
376 [ + + ]: 4204 : if (k >= endpos) {
377 : 4150 : i += (endpos - startpos - 1);
378 : 4150 : break;
379 : : }
380 : 54 : startpos = k;
381 : : assert(startpos < endpos);
382 : : /* fall through */
383 : 436 : default:
384 : 436 : rep = unicode_encode_call_errorhandler(
385 : : errors, &error_handler_obj, "utf-8", "surrogates not allowed",
386 : : unicode, &exc, startpos, endpos, &newpos);
387 [ + + ]: 436 : if (!rep)
388 : 379 : goto error;
389 : :
390 [ + + ]: 57 : if (newpos < startpos) {
391 : 51 : writer->overallocate = 1;
392 : 51 : p = _PyBytesWriter_Prepare(writer, p,
393 : 51 : max_char_size * (startpos - newpos));
394 [ - + ]: 51 : if (p == NULL)
395 : 0 : goto error;
396 : : }
397 : : else {
398 : : /* subtract preallocated bytes */
399 : 6 : writer->min_size -= max_char_size * (newpos - startpos);
400 : : /* Only overallocate the buffer if it's not the last write */
401 : 6 : writer->overallocate = (newpos < size);
402 : : }
403 : :
404 [ + + ]: 57 : if (PyBytes_Check(rep)) {
405 : 2 : p = _PyBytesWriter_WriteBytes(writer, p,
406 : 1 : PyBytes_AS_STRING(rep),
407 : : PyBytes_GET_SIZE(rep));
408 : : }
409 : : else {
410 : : /* rep is unicode */
411 [ - + ]: 56 : if (PyUnicode_READY(rep) < 0)
412 : 0 : goto error;
413 : :
414 [ + + ]: 56 : if (!PyUnicode_IS_ASCII(rep)) {
415 : 3 : raise_encode_exception(&exc, "utf-8", unicode,
416 : : startpos, endpos,
417 : : "surrogates not allowed");
418 : 3 : goto error;
419 : : }
420 : :
421 : 106 : p = _PyBytesWriter_WriteBytes(writer, p,
422 : 53 : PyUnicode_DATA(rep),
423 : : PyUnicode_GET_LENGTH(rep));
424 : : }
425 : :
426 [ - + ]: 54 : if (p == NULL)
427 : 0 : goto error;
428 [ + - ]: 54 : Py_CLEAR(rep);
429 : :
430 : 54 : i = newpos;
431 : : }
432 : :
433 : : /* If overallocation was disabled, ensure that it was the last
434 : : write. Otherwise, we missed an optimization */
435 : : assert(writer->overallocate || i == size);
436 : : }
437 : : else
438 : : #if STRINGLIB_SIZEOF_CHAR > 2
439 [ + + ]: 8527880 : if (ch < 0x10000)
440 : : #endif
441 : : {
442 : 1324310 : *p++ = (char)(0xe0 | (ch >> 12));
443 : 1324310 : *p++ = (char)(0x80 | ((ch >> 6) & 0x3f));
444 : 1324310 : *p++ = (char)(0x80 | (ch & 0x3f));
445 : : }
446 : : #if STRINGLIB_SIZEOF_CHAR > 2
447 : : else /* ch >= 0x10000 */
448 : : {
449 : : assert(ch <= MAX_UNICODE);
450 : : /* Encode UCS4 Unicode ordinals */
451 : 8423291 : *p++ = (char)(0xf0 | (ch >> 18));
452 : 8423291 : *p++ = (char)(0x80 | ((ch >> 12) & 0x3f));
453 : 8423291 : *p++ = (char)(0x80 | ((ch >> 6) & 0x3f));
454 : 8423291 : *p++ = (char)(0x80 | (ch & 0x3f));
455 : : }
456 : : #endif /* STRINGLIB_SIZEOF_CHAR > 2 */
457 : : #endif /* STRINGLIB_SIZEOF_CHAR > 1 */
458 : : }
459 : :
460 : : #if STRINGLIB_SIZEOF_CHAR > 1
461 : 1311007 : Py_XDECREF(error_handler_obj);
462 : 1311007 : Py_XDECREF(exc);
463 : : #endif
464 : 1499394 : return p;
465 : :
466 : : #if STRINGLIB_SIZEOF_CHAR > 1
467 : 382 : error:
468 : 382 : Py_XDECREF(rep);
469 : 382 : Py_XDECREF(error_handler_obj);
470 : 382 : Py_XDECREF(exc);
471 : 382 : return NULL;
472 : : #endif
473 : : }
474 : :
475 : : /* The pattern for constructing UCS2-repeated masks. */
476 : : #if SIZEOF_LONG == 8
477 : : # define UCS2_REPEAT_MASK 0x0001000100010001ul
478 : : #elif SIZEOF_LONG == 4
479 : : # define UCS2_REPEAT_MASK 0x00010001ul
480 : : #else
481 : : # error C 'long' size should be either 4 or 8!
482 : : #endif
483 : :
484 : : /* The mask for fast checking. */
485 : : #if STRINGLIB_SIZEOF_CHAR == 1
486 : : /* The mask for fast checking of whether a C 'long' contains a
487 : : non-ASCII or non-Latin1 UTF16-encoded characters. */
488 : : # define FAST_CHAR_MASK (UCS2_REPEAT_MASK * (0xFFFFu & ~STRINGLIB_MAX_CHAR))
489 : : #else
490 : : /* The mask for fast checking of whether a C 'long' may contain
491 : : UTF16-encoded surrogate characters. This is an efficient heuristic,
492 : : assuming that non-surrogate characters with a code point >= 0x8000 are
493 : : rare in most input.
494 : : */
495 : : # define FAST_CHAR_MASK (UCS2_REPEAT_MASK * 0x8000u)
496 : : #endif
497 : : /* The mask for fast byte-swapping. */
498 : : #define STRIPPED_MASK (UCS2_REPEAT_MASK * 0x00FFu)
499 : : /* Swap bytes. */
500 : : #define SWAB(value) ((((value) >> 8) & STRIPPED_MASK) | \
501 : : (((value) & STRIPPED_MASK) << 8))
502 : :
503 : : Py_LOCAL_INLINE(Py_UCS4)
504 : 35617 : STRINGLIB(utf16_decode)(const unsigned char **inptr, const unsigned char *e,
505 : : STRINGLIB_CHAR *dest, Py_ssize_t *outpos,
506 : : int native_ordering)
507 : : {
508 : : Py_UCS4 ch;
509 : 35617 : const unsigned char *q = *inptr;
510 : 35617 : STRINGLIB_CHAR *p = dest + *outpos;
511 : : /* Offsets from q for retrieving byte pairs in the right order. */
512 : : #if PY_LITTLE_ENDIAN
513 : 35617 : int ihi = !!native_ordering, ilo = !native_ordering;
514 : : #else
515 : : int ihi = !native_ordering, ilo = !!native_ordering;
516 : : #endif
517 : 35617 : --e;
518 : :
519 [ + + ]: 149276 : while (q < e) {
520 : : Py_UCS4 ch2;
521 : : /* First check for possible aligned read of a C 'long'. Unaligned
522 : : reads are more expensive, better to defer to another iteration. */
523 [ + + ]: 120891 : if (_Py_IS_ALIGNED(q, ALIGNOF_LONG)) {
524 : : /* Fast path for runs of in-range non-surrogate chars. */
525 : 34190 : const unsigned char *_q = q;
526 [ + + ]: 238329 : while (_q + SIZEOF_LONG <= e) {
527 : 208001 : unsigned long block = * (const unsigned long *) _q;
528 [ + + ]: 208001 : if (native_ordering) {
529 : : /* Can use buffer directly */
530 [ + + ]: 139938 : if (block & FAST_CHAR_MASK)
531 : 2545 : break;
532 : : }
533 : : else {
534 : : /* Need to byte-swap */
535 [ + + ]: 68063 : if (block & SWAB(FAST_CHAR_MASK))
536 : 1317 : break;
537 : : #if STRINGLIB_SIZEOF_CHAR == 1
538 : 61077 : block >>= 8;
539 : : #else
540 : 5669 : block = SWAB(block);
541 : : #endif
542 : : }
543 : : #if PY_LITTLE_ENDIAN
544 : : # if SIZEOF_LONG == 4
545 : : p[0] = (STRINGLIB_CHAR)(block & 0xFFFFu);
546 : : p[1] = (STRINGLIB_CHAR)(block >> 16);
547 : : # elif SIZEOF_LONG == 8
548 : 204139 : p[0] = (STRINGLIB_CHAR)(block & 0xFFFFu);
549 : 204139 : p[1] = (STRINGLIB_CHAR)((block >> 16) & 0xFFFFu);
550 : 204139 : p[2] = (STRINGLIB_CHAR)((block >> 32) & 0xFFFFu);
551 : 204139 : p[3] = (STRINGLIB_CHAR)(block >> 48);
552 : : # endif
553 : : #else
554 : : # if SIZEOF_LONG == 4
555 : : p[0] = (STRINGLIB_CHAR)(block >> 16);
556 : : p[1] = (STRINGLIB_CHAR)(block & 0xFFFFu);
557 : : # elif SIZEOF_LONG == 8
558 : : p[0] = (STRINGLIB_CHAR)(block >> 48);
559 : : p[1] = (STRINGLIB_CHAR)((block >> 32) & 0xFFFFu);
560 : : p[2] = (STRINGLIB_CHAR)((block >> 16) & 0xFFFFu);
561 : : p[3] = (STRINGLIB_CHAR)(block & 0xFFFFu);
562 : : # endif
563 : : #endif
564 : 204139 : _q += SIZEOF_LONG;
565 : 204139 : p += SIZEOF_LONG / 2;
566 : : }
567 : 34190 : q = _q;
568 [ + + ]: 34190 : if (q >= e)
569 : 88 : break;
570 : : }
571 : :
572 : 120803 : ch = (q[ihi] << 8) | q[ilo];
573 : 120803 : q += 2;
574 [ + + ]: 120803 : if (!Py_UNICODE_IS_SURROGATE(ch)) {
575 : : #if STRINGLIB_SIZEOF_CHAR < 2
576 [ + + ]: 99890 : if (ch > STRINGLIB_MAX_CHAR)
577 : : /* Out-of-range */
578 : 6930 : goto Return;
579 : : #endif
580 : 113639 : *p++ = (STRINGLIB_CHAR)ch;
581 : 113639 : continue;
582 : : }
583 : :
584 : : /* UTF-16 code pair: */
585 [ + + ]: 234 : if (!Py_UNICODE_IS_HIGH_SURROGATE(ch))
586 : 105 : goto IllegalEncoding;
587 [ + + ]: 129 : if (q >= e)
588 : 44 : goto UnexpectedEnd;
589 : 85 : ch2 = (q[ihi] << 8) | q[ilo];
590 : 85 : q += 2;
591 [ + + ]: 85 : if (!Py_UNICODE_IS_LOW_SURROGATE(ch2))
592 : 12 : goto IllegalSurrogate;
593 : 73 : ch = Py_UNICODE_JOIN_SURROGATES(ch, ch2);
594 : : #if STRINGLIB_SIZEOF_CHAR < 4
595 : : /* Out-of-range */
596 : 53 : goto Return;
597 : : #else
598 : 20 : *p++ = (STRINGLIB_CHAR)ch;
599 : : #endif
600 : : }
601 : 28473 : ch = 0;
602 : 35617 : Return:
603 : 35617 : *inptr = q;
604 : 35617 : *outpos = p - dest;
605 : 35617 : return ch;
606 : 44 : UnexpectedEnd:
607 : 44 : ch = 1;
608 : 44 : goto Return;
609 : 105 : IllegalEncoding:
610 : 105 : ch = 2;
611 : 105 : goto Return;
612 : 12 : IllegalSurrogate:
613 : 12 : ch = 3;
614 : 12 : goto Return;
615 : : }
616 : : #undef UCS2_REPEAT_MASK
617 : : #undef FAST_CHAR_MASK
618 : : #undef STRIPPED_MASK
619 : : #undef SWAB
620 : :
621 : :
622 : : #if STRINGLIB_MAX_CHAR >= 0x80
623 : : Py_LOCAL_INLINE(Py_ssize_t)
624 : 5979 : STRINGLIB(utf16_encode)(const STRINGLIB_CHAR *in,
625 : : Py_ssize_t len,
626 : : unsigned short **outptr,
627 : : int native_ordering)
628 : : {
629 : 5979 : unsigned short *out = *outptr;
630 : 5979 : const STRINGLIB_CHAR *end = in + len;
631 : : #if STRINGLIB_SIZEOF_CHAR == 1
632 [ + + ]: 2912 : if (native_ordering) {
633 : 2010 : const STRINGLIB_CHAR *unrolled_end = in + _Py_SIZE_ROUND_DOWN(len, 4);
634 [ + + ]: 125307 : while (in < unrolled_end) {
635 : 123297 : out[0] = in[0];
636 : 123297 : out[1] = in[1];
637 : 123297 : out[2] = in[2];
638 : 123297 : out[3] = in[3];
639 : 123297 : in += 4; out += 4;
640 : : }
641 [ + + ]: 4149 : while (in < end) {
642 : 2139 : *out++ = *in++;
643 : : }
644 : : } else {
645 : : # define SWAB2(CH) ((CH) << 8) /* high byte is zero */
646 : 902 : const STRINGLIB_CHAR *unrolled_end = in + _Py_SIZE_ROUND_DOWN(len, 4);
647 [ + + ]: 56481 : while (in < unrolled_end) {
648 : 55579 : out[0] = SWAB2(in[0]);
649 : 55579 : out[1] = SWAB2(in[1]);
650 : 55579 : out[2] = SWAB2(in[2]);
651 : 55579 : out[3] = SWAB2(in[3]);
652 : 55579 : in += 4; out += 4;
653 : : }
654 [ + + ]: 1856 : while (in < end) {
655 : 954 : Py_UCS4 ch = *in++;
656 : 954 : *out++ = SWAB2((Py_UCS2)ch);
657 : : }
658 : : #undef SWAB2
659 : : }
660 : 2912 : *outptr = out;
661 : 2912 : return len;
662 : : #else
663 [ + + ]: 3067 : if (native_ordering) {
664 : : #if STRINGLIB_MAX_CHAR < 0x10000
665 : 2026 : const STRINGLIB_CHAR *unrolled_end = in + _Py_SIZE_ROUND_DOWN(len, 4);
666 [ + + ]: 42796 : while (in < unrolled_end) {
667 : : /* check if any character is a surrogate character */
668 : 40774 : if (((in[0] ^ 0xd800) &
669 : 40774 : (in[1] ^ 0xd800) &
670 : 40774 : (in[2] ^ 0xd800) &
671 [ + + ]: 40774 : (in[3] ^ 0xd800) & 0xf800) == 0)
672 : 4 : break;
673 : 40770 : out[0] = in[0];
674 : 40770 : out[1] = in[1];
675 : 40770 : out[2] = in[2];
676 : 40770 : out[3] = in[3];
677 : 40770 : in += 4; out += 4;
678 : : }
679 : : #endif
680 [ + + ]: 4977 : while (in < end) {
681 : : Py_UCS4 ch;
682 : 2998 : ch = *in++;
683 [ + + ]: 2998 : if (ch < 0xd800)
684 : 2842 : *out++ = ch;
685 [ + + ]: 156 : else if (ch < 0xe000)
686 : : /* reject surrogate characters (U+D800-U+DFFF) */
687 : 87 : goto fail;
688 : : #if STRINGLIB_MAX_CHAR >= 0x10000
689 [ + + ]: 69 : else if (ch >= 0x10000) {
690 : 61 : out[0] = Py_UNICODE_HIGH_SURROGATE(ch);
691 : 61 : out[1] = Py_UNICODE_LOW_SURROGATE(ch);
692 : 61 : out += 2;
693 : : }
694 : : #endif
695 : : else
696 : 8 : *out++ = ch;
697 : : }
698 : : } else {
699 : : #define SWAB2(CH) (((CH) << 8) | ((CH) >> 8))
700 : : #if STRINGLIB_MAX_CHAR < 0x10000
701 : 979 : const STRINGLIB_CHAR *unrolled_end = in + _Py_SIZE_ROUND_DOWN(len, 4);
702 [ + + ]: 19826 : while (in < unrolled_end) {
703 : : /* check if any character is a surrogate character */
704 : 18849 : if (((in[0] ^ 0xd800) &
705 : 18849 : (in[1] ^ 0xd800) &
706 : 18849 : (in[2] ^ 0xd800) &
707 [ + + ]: 18849 : (in[3] ^ 0xd800) & 0xf800) == 0)
708 : 2 : break;
709 : 18847 : out[0] = SWAB2(in[0]);
710 : 18847 : out[1] = SWAB2(in[1]);
711 : 18847 : out[2] = SWAB2(in[2]);
712 : 18847 : out[3] = SWAB2(in[3]);
713 : 18847 : in += 4; out += 4;
714 : : }
715 : : #endif
716 [ + + ]: 2452 : while (in < end) {
717 : 1471 : Py_UCS4 ch = *in++;
718 [ + + ]: 1471 : if (ch < 0xd800)
719 : 1414 : *out++ = SWAB2((Py_UCS2)ch);
720 [ + + ]: 57 : else if (ch < 0xe000)
721 : : /* reject surrogate characters (U+D800-U+DFFF) */
722 : 20 : goto fail;
723 : : #if STRINGLIB_MAX_CHAR >= 0x10000
724 [ + + ]: 37 : else if (ch >= 0x10000) {
725 : 33 : Py_UCS2 ch1 = Py_UNICODE_HIGH_SURROGATE(ch);
726 : 33 : Py_UCS2 ch2 = Py_UNICODE_LOW_SURROGATE(ch);
727 : 33 : out[0] = SWAB2(ch1);
728 : 33 : out[1] = SWAB2(ch2);
729 : 33 : out += 2;
730 : : }
731 : : #endif
732 : : else
733 : 4 : *out++ = SWAB2((Py_UCS2)ch);
734 : : }
735 : : #undef SWAB2
736 : : }
737 : 2960 : *outptr = out;
738 : 2960 : return len;
739 : 107 : fail:
740 : 107 : *outptr = out;
741 : 107 : return len - (end - in + 1);
742 : : #endif
743 : : }
744 : :
745 : : static inline uint32_t
746 : 294777 : STRINGLIB(SWAB4)(STRINGLIB_CHAR ch)
747 : : {
748 : 294777 : uint32_t word = ch;
749 : : #if STRINGLIB_SIZEOF_CHAR == 1
750 : : /* high bytes are zero */
751 : 219139 : return (word << 24);
752 : : #elif STRINGLIB_SIZEOF_CHAR == 2
753 : : /* high bytes are zero */
754 : 75595 : return ((word & 0x00FFu) << 24) | ((word & 0xFF00u) << 8);
755 : : #else
756 : 43 : return _Py_bswap32(word);
757 : : #endif
758 : : }
759 : :
760 : : Py_LOCAL_INLINE(Py_ssize_t)
761 : 2618 : STRINGLIB(utf32_encode)(const STRINGLIB_CHAR *in,
762 : : Py_ssize_t len,
763 : : uint32_t **outptr,
764 : : int native_ordering)
765 : : {
766 : 2618 : uint32_t *out = *outptr;
767 : 2618 : const STRINGLIB_CHAR *end = in + len;
768 [ + + ]: 2618 : if (native_ordering) {
769 : 1817 : const STRINGLIB_CHAR *unrolled_end = in + _Py_SIZE_ROUND_DOWN(len, 4);
770 [ + + ]: 162449 : while (in < unrolled_end) {
771 : : #if STRINGLIB_SIZEOF_CHAR > 1
772 : : /* check if any character is a surrogate character */
773 : 40756 : if (((in[0] ^ 0xd800) &
774 : 40756 : (in[1] ^ 0xd800) &
775 : 40756 : (in[2] ^ 0xd800) &
776 [ + + ]: 40756 : (in[3] ^ 0xd800) & 0xf800) == 0)
777 : 12 : break;
778 : : #endif
779 : 160632 : out[0] = in[0];
780 : 160632 : out[1] = in[1];
781 : 160632 : out[2] = in[2];
782 : 160632 : out[3] = in[3];
783 : 160632 : in += 4; out += 4;
784 : : }
785 [ + + ]: 3697 : while (in < end) {
786 : : Py_UCS4 ch;
787 : 1969 : ch = *in++;
788 : : #if STRINGLIB_SIZEOF_CHAR > 1
789 [ + + ]: 568 : if (Py_UNICODE_IS_SURROGATE(ch)) {
790 : : /* reject surrogate characters (U+D800-U+DFFF) */
791 : 89 : goto fail;
792 : : }
793 : : #endif
794 : 1880 : *out++ = ch;
795 : : }
796 : : } else {
797 : 801 : const STRINGLIB_CHAR *unrolled_end = in + _Py_SIZE_ROUND_DOWN(len, 4);
798 [ + + ]: 74285 : while (in < unrolled_end) {
799 : : #if STRINGLIB_SIZEOF_CHAR > 1
800 : : /* check if any character is a surrogate character */
801 : 18856 : if (((in[0] ^ 0xd800) &
802 : 18856 : (in[1] ^ 0xd800) &
803 : 18856 : (in[2] ^ 0xd800) &
804 [ + + ]: 18856 : (in[3] ^ 0xd800) & 0xf800) == 0)
805 : 6 : break;
806 : : #endif
807 : 73484 : out[0] = STRINGLIB(SWAB4)(in[0]);
808 : 73484 : out[1] = STRINGLIB(SWAB4)(in[1]);
809 : 73484 : out[2] = STRINGLIB(SWAB4)(in[2]);
810 : 73484 : out[3] = STRINGLIB(SWAB4)(in[3]);
811 : 73484 : in += 4; out += 4;
812 : : }
813 [ + + ]: 1642 : while (in < end) {
814 : 861 : Py_UCS4 ch = *in++;
815 : : #if STRINGLIB_SIZEOF_CHAR > 1
816 [ + + ]: 258 : if (Py_UNICODE_IS_SURROGATE(ch)) {
817 : : /* reject surrogate characters (U+D800-U+DFFF) */
818 : 20 : goto fail;
819 : : }
820 : : #endif
821 : 841 : *out++ = STRINGLIB(SWAB4)(ch);
822 : : }
823 : : }
824 : 2509 : *outptr = out;
825 : 2509 : return len;
826 : : #if STRINGLIB_SIZEOF_CHAR > 1
827 : 109 : fail:
828 : 109 : *outptr = out;
829 : 109 : return len - (end - in + 1);
830 : : #endif
831 : : }
832 : :
833 : : #endif
|