FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

GitHub Viewer

/* stringlib: codec implementations */ #if STRINGLIB_IS_UNICODE /* Mask to quickly check whether a C 'long' contains a non-ASCII, UTF8-encoded char. */ #if (SIZEOF_LONG == 8) # define ASCII_CHAR_MASK 0x8080808080808080UL #elif (SIZEOF_LONG == 4) # define ASCII_CHAR_MASK 0x80808080UL #else # error C 'long' size should be either 4 or 8! #endif /* 10xxxxxx */ #define IS_CONTINUATION_BYTE(ch) ((ch) >= 0x80 && (ch) < 0xC0) Py_LOCAL_INLINE(Py_UCS4) STRINGLIB(utf8_decode)(const char **inptr, const char *end, STRINGLIB_CHAR *dest, Py_ssize_t *outpos) { Py_UCS4 ch; const char *s = *inptr; const char *aligned_end = (const char *) _Py_ALIGN_DOWN(end, SIZEOF_LONG); STRINGLIB_CHAR *p = dest + *outpos; while (s < end) { ch = (unsigned char)*s; if (ch < 0x80) { /* Fast path for runs of ASCII characters. Given that common UTF-8 input will consist of an overwhelming majority of ASCII characters, we try to optimize for this case by checking as many characters as a C 'long' can contain. First, check if we can do an aligned read, as most CPUs have a penalty for unaligned reads. */ if (_Py_IS_ALIGNED(s, SIZEOF_LONG)) { /* Help register allocation */ const char *_s = s; STRINGLIB_CHAR *_p = p; while (_s < aligned_end) { /* Read a whole long at a time (either 4 or 8 bytes), and do a fast unrolled copy if it only contains ASCII characters. */ unsigned long value = *(unsigned long *) _s; if (value & ASCII_CHAR_MASK) break; #if PY_LITTLE_ENDIAN _p[0] = (STRINGLIB_CHAR)(value & 0xFFu); _p[1] = (STRINGLIB_CHAR)((value >> 8) & 0xFFu); _p[2] = (STRINGLIB_CHAR)((value >> 16) & 0xFFu); _p[3] = (STRINGLIB_CHAR)((value >> 24) & 0xFFu); # if SIZEOF_LONG == 8 _p[4] = (STRINGLIB_CHAR)((value >> 32) & 0xFFu); _p[5] = (STRINGLIB_CHAR)((value >> 40) & 0xFFu); _p[6] = (STRINGLIB_CHAR)((value >> 48) & 0xFFu); _p[7] = (STRINGLIB_CHAR)((value >> 56) & 0xFFu); # endif #else # if SIZEOF_LONG == 8 _p[0] = (STRINGLIB_CHAR)((value >> 56) & 0xFFu); _p[1] = (STRINGLIB_CHAR)((value >> 48) & 0xFFu); _p[2] = (STRINGLIB_CHAR)((value >> 40) & 0xFFu); _p[3] = (STRINGLIB_CHAR)((value >> 32) & 0xFFu); _p[4] = (STRINGLIB_CHAR)((value >> 24) & 0xFFu); _p[5] = (STRINGLIB_CHAR)((value >> 16) & 0xFFu); _p[6] = (STRINGLIB_CHAR)((value >> 8) & 0xFFu); _p[7] = (STRINGLIB_CHAR)(value & 0xFFu); # else _p[0] = (STRINGLIB_CHAR)((value >> 24) & 0xFFu); _p[1] = (STRINGLIB_CHAR)((value >> 16) & 0xFFu); _p[2] = (STRINGLIB_CHAR)((value >> 8) & 0xFFu); _p[3] = (STRINGLIB_CHAR)(value & 0xFFu); # endif #endif _s += SIZEOF_LONG; _p += SIZEOF_LONG; } s = _s; p = _p; if (s == end) break; ch = (unsigned char)*s; } if (ch < 0x80) { s++; *p++ = ch; continue; } } if (ch < 0xE0) { /* \xC2\x80-\xDF\xBF -- 0080-07FF */ Py_UCS4 ch2; if (ch < 0xC2) { /* invalid sequence \x80-\xBF -- continuation byte \xC0-\xC1 -- fake 0000-007F */ goto InvalidStart; } if (end - s < 2) { /* unexpected end of data: the caller will decide whether it's an error or not */ break; } ch2 = (unsigned char)s[1]; if (!IS_CONTINUATION_BYTE(ch2)) /* invalid continuation byte */ goto InvalidContinuation1; ch = (ch = 0x90) { /* invalid sequence \xF4\x90\x80\80- -- 110000- overflow */ goto InvalidContinuation1; } if (!IS_CONTINUATION_BYTE(ch3)) { /* invalid continuation byte */ goto InvalidContinuation2; } if (!IS_CONTINUATION_BYTE(ch4)) { /* invalid continuation byte */ goto InvalidContinuation3; } ch = (ch

Back | FazBrowse Home | New Git URL