@@ -51,7 +51,7 @@ typedef struct _PyEncoderObject {
5151 char sort_keys ;
5252 char skipkeys ;
5353 int allow_nan ;
54- PyObject * (* fast_encode )(PyObject * );
54+ int (* fast_encode )(PyUnicodeWriter * , PyObject * );
5555} PyEncoderObject ;
5656
5757#define PyEncoderObject_CAST (op ) ((PyEncoderObject *)(op))
@@ -103,6 +103,8 @@ _encoded_const(PyObject *obj);
103103static void
104104raise_errmsg (const char * msg , PyObject * s , Py_ssize_t end );
105105static int
106+ _steal_accumulate (PyUnicodeWriter * writer , PyObject * stolen );
107+ static int
106108encoder_write_string (PyEncoderObject * s , PyUnicodeWriter * writer , PyObject * obj );
107109static PyObject *
108110encoder_encode_float (PyEncoderObject * s , PyObject * obj );
@@ -209,8 +211,8 @@ ascii_escape_unicode(PyObject *pystr)
209211 return rval ;
210212}
211213
212- static PyObject *
213- ascii_escape_unicode_ex ( PyObject * pystr )
214+ static int
215+ write_escaped_ascii ( PyUnicodeWriter * writer , PyObject * pystr )
214216{
215217 /* Take a PyUnicode pystr and return a new ASCII-only escaped PyUnicode */
216218 Py_ssize_t i ;
@@ -227,7 +229,7 @@ ascii_escape_unicode_ex(PyObject *pystr)
227229 kind = PyUnicode_KIND (pystr );
228230
229231 /* Compute the output size */
230- for (i = 0 , output_size = 0 ; i < input_chars ; i ++ ) {
232+ for (i = 0 , output_size = 2 ; i < input_chars ; i ++ ) {
231233 Py_UCS4 c = PyUnicode_READ (kind , input , i );
232234 Py_ssize_t d ;
233235 if (S_CHAR (c )) {
@@ -244,22 +246,29 @@ ascii_escape_unicode_ex(PyObject *pystr)
244246 }
245247 if (output_size > PY_SSIZE_T_MAX - d ) {
246248 PyErr_SetString (PyExc_OverflowError , "string is too long to escape" );
247- return NULL ;
249+ return -1 ;
248250 }
249251 output_size += d ;
250252 }
251253
252- if (output_size == input_chars ) {
254+ if (output_size == input_chars + 2 ) {
253255 /* No need to escape anything */
254- return Py_NewRef (pystr );
256+ if (PyUnicodeWriter_WriteChar (writer , '"' ) < 0 ) {
257+ return -1 ;
258+ }
259+ if (PyUnicodeWriter_WriteStr (writer , pystr ) < 0 ) {
260+ return -1 ;
261+ }
262+ return PyUnicodeWriter_WriteChar (writer , '"' );
255263 }
256264
257265 rval = PyUnicode_New (output_size , 127 );
258266 if (rval == NULL ) {
259- return NULL ;
267+ return -1 ;
260268 }
261269 output = PyUnicode_1BYTE_DATA (rval );
262270 chars = 0 ;
271+ output [chars ++ ] = '"' ;
263272 for (i = 0 ; i < input_chars ; i ++ ) {
264273 Py_UCS4 c = PyUnicode_READ (kind , input , i );
265274 if (S_CHAR (c )) {
@@ -269,10 +278,11 @@ ascii_escape_unicode_ex(PyObject *pystr)
269278 chars = ascii_escape_unichar (c , output , chars );
270279 }
271280 }
281+ output [chars ++ ] = '"' ;
272282#ifdef Py_DEBUG
273283 assert (_PyUnicode_CheckConsistency (rval , 1 ));
274284#endif
275- return rval ;
285+ return _steal_accumulate ( writer , rval ) ;
276286}
277287
278288static PyObject *
@@ -369,8 +379,8 @@ escape_unicode(PyObject *pystr)
369379 return rval ;
370380}
371381
372- static PyObject *
373- escape_unicode_ex ( PyObject * pystr )
382+ static int
383+ write_escaped_unicode ( PyUnicodeWriter * writer , PyObject * pystr )
374384{
375385 /* Take a PyUnicode pystr and return a new escaped PyUnicode */
376386 Py_ssize_t i ;
@@ -388,7 +398,7 @@ escape_unicode_ex(PyObject *pystr)
388398 kind = PyUnicode_KIND (pystr );
389399
390400 /* Compute the output size */
391- for (i = 0 , output_size = 0 ; i < input_chars ; i ++ ) {
401+ for (i = 0 , output_size = 2 ; i < input_chars ; i ++ ) {
392402 Py_UCS4 c = PyUnicode_READ (kind , input , i );
393403 Py_ssize_t d ;
394404 switch (c ) {
@@ -404,24 +414,31 @@ escape_unicode_ex(PyObject *pystr)
404414 }
405415 if (output_size > PY_SSIZE_T_MAX - d ) {
406416 PyErr_SetString (PyExc_OverflowError , "string is too long to escape" );
407- return NULL ;
417+ return -1 ;
408418 }
409419 output_size += d ;
410420 }
411421
412- if (output_size == input_chars ) {
422+ if (output_size == input_chars + 2 ) {
413423 /* No need to escape anything */
414- return Py_NewRef (pystr );
424+ if (PyUnicodeWriter_WriteChar (writer , '"' ) < 0 ) {
425+ return -1 ;
426+ }
427+ if (PyUnicodeWriter_WriteStr (writer , pystr ) < 0 ) {
428+ return -1 ;
429+ }
430+ return PyUnicodeWriter_WriteChar (writer , '"' );
415431 }
416432
417433 rval = PyUnicode_New (output_size , maxchar );
418434 if (rval == NULL )
419- return NULL ;
435+ return -1 ;
420436
421437 kind = PyUnicode_KIND (rval );
422438
423439#define ENCODE_OUTPUT do { \
424440 chars = 0; \
441+ output[chars++] = '"'; \
425442 for (i = 0; i < input_chars; i++) { \
426443 Py_UCS4 c = PyUnicode_READ(kind, input, i); \
427444 switch (c) { \
@@ -445,6 +462,7 @@ escape_unicode_ex(PyObject *pystr)
445462 } \
446463 } \
447464 } \
465+ output[chars++] = '"'; \
448466 } while (0)
449467
450468 if (kind == PyUnicode_1BYTE_KIND ) {
@@ -463,7 +481,7 @@ escape_unicode_ex(PyObject *pystr)
463481#ifdef Py_DEBUG
464482 assert (_PyUnicode_CheckConsistency (rval , 1 ));
465483#endif
466- return rval ;
484+ return _steal_accumulate ( writer , rval ) ;
467485}
468486
469487static void
@@ -1419,10 +1437,10 @@ encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
14191437 if (PyCFunction_Check (s -> encoder )) {
14201438 PyCFunction f = PyCFunction_GetFunction (s -> encoder );
14211439 if (f == py_encode_basestring_ascii ) {
1422- s -> fast_encode = ascii_escape_unicode_ex ;
1440+ s -> fast_encode = write_escaped_ascii ;
14231441 }
14241442 else if (f == py_encode_basestring ) {
1425- s -> fast_encode = escape_unicode_ex ;
1443+ s -> fast_encode = write_escaped_unicode ;
14261444 }
14271445 }
14281446
@@ -1619,17 +1637,7 @@ encoder_write_string(PyEncoderObject *s, PyUnicodeWriter *writer, PyObject *obj)
16191637 PyObject * encoded ;
16201638
16211639 if (s -> fast_encode ) {
1622- if (PyUnicodeWriter_WriteChar (writer , '"' ) < 0 ) {
1623- return -1 ;
1624- }
1625- encoded = s -> fast_encode (obj );
1626- if (encoded == NULL ) {
1627- return -1 ;
1628- }
1629- if (_steal_accumulate (writer , encoded ) < 0 ) {
1630- return -1 ;
1631- }
1632- return PyUnicodeWriter_WriteChar (writer , '"' );
1640+ return s -> fast_encode (writer , obj );
16331641 }
16341642 encoded = PyObject_CallOneArg (s -> encoder , obj );
16351643 if (encoded == NULL ) {
0 commit comments