| /* stringlib: repr() implementation */ | |
| #ifndef STRINGLIB_FASTSEARCH_H | |
| #error must include "stringlib/fastsearch.h" before including this module | |
| #endif | |
| static void | |
| STRINGLIB(repr)(PyObject *unicode, Py_UCS4 quote, | |
| STRINGLIB_CHAR *odata) | |
| { | |
| Py_ssize_t isize = PyUnicode_GET_LENGTH(unicode); | |
| const void *idata = PyUnicode_DATA(unicode); | |
| int ikind = PyUnicode_KIND(unicode); | |
| *odata++ = quote; | |
| for (Py_ssize_t i = 0; i < isize; i++) { | |
| Py_UCS4 ch = PyUnicode_READ(ikind, idata, i); | |
| /* Escape quotes and backslashes */ | |
| if ((ch == quote) || (ch == '\\')) { | |
| *odata++ = '\\'; | |
| *odata++ = ch; | |
| continue; | |
| } | |
| /* Map special whitespace to '\t', \n', '\r' */ | |
| if (ch == '\t') { | |
| *odata++ = '\\'; | |
| *odata++ = 't'; | |
| } | |
| else if (ch == '\n') { | |
| *odata++ = '\\'; | |
| *odata++ = 'n'; | |
| } | |
| else if (ch == '\r') { | |
| *odata++ = '\\'; | |
| *odata++ = 'r'; | |
| } | |
| /* Map non-printable US ASCII to '\xhh' */ | |
| else if (ch < ' ' || ch == 0x7F) { | |
| *odata++ = '\\'; | |
| *odata++ = 'x'; | |
| *odata++ = Py_hexdigits[(ch >> 4) & 0x000F]; | |
| *odata++ = Py_hexdigits[ch & 0x000F]; | |
| } | |
| /* Copy ASCII characters as-is */ | |
| else if (ch < 0x7F) { | |
| *odata++ = ch; | |
| } | |
| /* Non-ASCII characters */ | |
| else { | |
| /* Map Unicode whitespace and control characters | |
| (categories Z* and C* except ASCII space) | |
| */ | |
| if (!Py_UNICODE_ISPRINTABLE(ch)) { | |
| *odata++ = '\\'; | |
| /* Map 8-bit characters to '\xhh' */ | |
| if (ch <= 0xff) { | |
| *odata++ = 'x'; | |
| *odata++ = Py_hexdigits[(ch >> 4) & 0x000F]; | |
| *odata++ = Py_hexdigits[ch & 0x000F]; | |
| } | |
| /* Map 16-bit characters to '\uxxxx' */ | |
| else if (ch <= 0xffff) { | |
| *odata++ = 'u'; | |
| *odata++ = Py_hexdigits[(ch >> 12) & 0xF]; | |
| *odata++ = Py_hexdigits[(ch >> 8) & 0xF]; | |
| *odata++ = Py_hexdigits[(ch >> 4) & 0xF]; | |
| *odata++ = Py_hexdigits[ch & 0xF]; | |
| } | |
| /* Map 21-bit characters to '\U00xxxxxx' */ | |
| else { | |
| *odata++ = 'U'; | |
| *odata++ = Py_hexdigits[(ch >> 28) & 0xF]; | |
| *odata++ = Py_hexdigits[(ch >> 24) & 0xF]; | |
| *odata++ = Py_hexdigits[(ch >> 20) & 0xF]; | |
| *odata++ = Py_hexdigits[(ch >> 16) & 0xF]; | |
| *odata++ = Py_hexdigits[(ch >> 12) & 0xF]; | |
| *odata++ = Py_hexdigits[(ch >> 8) & 0xF]; | |
| *odata++ = Py_hexdigits[(ch >> 4) & 0xF]; | |
| *odata++ = Py_hexdigits[ch & 0xF]; | |
| } | |
| } | |
| /* Copy characters as-is */ | |
| else { | |
| *odata++ = ch; | |
| } | |
| } | |
| } | |
| *odata = quote; | |
| } |