]> granicus.if.org Git - python/commitdiff
Issue #25318: Avoid sprintf() in backslashreplace()
authorVictor Stinner <victor.stinner@gmail.com>
Fri, 9 Oct 2015 01:17:30 +0000 (03:17 +0200)
committerVictor Stinner <victor.stinner@gmail.com>
Fri, 9 Oct 2015 01:17:30 +0000 (03:17 +0200)
Rewrite backslashreplace() to be closer to PyCodec_BackslashReplaceErrors().

Add also unit tests for non-BMP characters.

Lib/test/test_codecs.py
Objects/unicodeobject.c

index 7b6883fcc51d374306e8afaad31198acefd5f851..ff314b10fbdda32c1db87070bb8468fe1a3f33dc 100644 (file)
@@ -3155,7 +3155,8 @@ class ASCIITest(unittest.TestCase):
             ('[\x80\xff\u20ac]', 'ignore', b'[]'),
             ('[\x80\xff\u20ac]', 'replace', b'[???]'),
             ('[\x80\xff\u20ac]', 'xmlcharrefreplace', b'[&#128;&#255;&#8364;]'),
-            ('[\x80\xff\u20ac]', 'backslashreplace', b'[\\x80\\xff\\u20ac]'),
+            ('[\x80\xff\u20ac\U000abcde]', 'backslashreplace',
+             b'[\\x80\\xff\\u20ac\\U000abcde]'),
             ('[\udc80\udcff]', 'surrogateescape', b'[\x80\xff]'),
         ):
             with self.subTest(data=data, error_handler=error_handler,
@@ -3197,7 +3198,8 @@ class Latin1Test(unittest.TestCase):
         for data, error_handler, expected in (
             ('[\u20ac\udc80]', 'ignore', b'[]'),
             ('[\u20ac\udc80]', 'replace', b'[??]'),
-            ('[\u20ac\udc80]', 'backslashreplace', b'[\\u20ac\\udc80]'),
+            ('[\u20ac\U000abcde]', 'backslashreplace',
+             b'[\\u20ac\\U000abcde]'),
             ('[\u20ac\udc80]', 'xmlcharrefreplace', b'[&#8364;&#56448;]'),
             ('[\udc80\udcff]', 'surrogateescape', b'[\x80\xff]'),
         ):
index 614d2147cb896b163bf2c16592fe68396c9683ca..10cdcc0ec001ddfba41bfc5bf157aef0959d1121 100644 (file)
@@ -610,14 +610,25 @@ backslashreplace(_PyBytesWriter *writer, Py_ssize_t prealloc_per_char,
     /* generate replacement */
     for (i = collstart; i < collend; ++i) {
         ch = PyUnicode_READ(kind, data, i);
-        if (ch < 0x100)
-            str += sprintf(str, "\\x%02x", ch);
-        else if (ch < 0x10000)
-            str += sprintf(str, "\\u%04x", ch);
-        else {
-            assert(ch <= MAX_UNICODE);
-            str += sprintf(str, "\\U%08x", ch);
+        *str++ = '\\';
+        if (ch >= 0x00010000) {
+            *str++ = 'U';
+            *str++ = Py_hexdigits[(ch>>28)&0xf];
+            *str++ = Py_hexdigits[(ch>>24)&0xf];
+            *str++ = Py_hexdigits[(ch>>20)&0xf];
+            *str++ = Py_hexdigits[(ch>>16)&0xf];
+            *str++ = Py_hexdigits[(ch>>12)&0xf];
+            *str++ = Py_hexdigits[(ch>>8)&0xf];
+        }
+        else if (ch >= 0x100) {
+            *str++ = 'u';
+            *str++ = Py_hexdigits[(ch>>12)&0xf];
+            *str++ = Py_hexdigits[(ch>>8)&0xf];
         }
+        else
+            *str++ = 'x';
+        *str++ = Py_hexdigits[(ch>>4)&0xf];
+        *str++ = Py_hexdigits[ch&0xf];
     }
     return str;
 }