@@ -2552,14 +2552,59 @@ escaped_char_size(Py_UCS4 ch, int flags)
25522552 }
25532553}
25542554
2555+ /* Write the escaped form of the character.
2556+ The writer buffer must have enough space reserved. */
2557+ static void
2558+ unicode_write_escaped_char (_PyUnicodeWriter * writer , Py_UCS4 ch , int flags )
2559+ {
2560+ int kind = writer -> kind ;
2561+ void * data = writer -> data ;
2562+ Py_ssize_t o = writer -> pos ;
2563+ switch (escaped_char_size (ch , flags )) {
2564+ case 1 :
2565+ PyUnicode_WRITE (kind , data , o ++ , ch );
2566+ break ;
2567+ case 2 :
2568+ PyUnicode_WRITE (kind , data , o ++ , '\\' );
2569+ switch (ch ) {
2570+ case '\t' : ch = 't' ; break ;
2571+ case '\r' : ch = 'r' ; break ;
2572+ case '\n' : ch = 'n' ; break ;
2573+ }
2574+ PyUnicode_WRITE (kind , data , o ++ , ch );
2575+ break ;
2576+ case 4 :
2577+ PyUnicode_WRITE (kind , data , o ++ , '\\' );
2578+ PyUnicode_WRITE (kind , data , o ++ , 'x' );
2579+ PyUnicode_WRITE (kind , data , o ++ , Py_hexdigits [(ch >> 4 ) & 0xf ]);
2580+ PyUnicode_WRITE (kind , data , o ++ , Py_hexdigits [ch & 0xf ]);
2581+ break ;
2582+ default :
2583+ {
2584+ int ndigits = (ch < 0x10000 ) ? 4 : 8 ;
2585+ PyUnicode_WRITE (kind , data , o ++ , '\\' );
2586+ PyUnicode_WRITE (kind , data , o ++ , (ch < 0x10000 ) ? 'u' : 'U' );
2587+ while (-- ndigits >= 0 ) {
2588+ PyUnicode_WRITE (kind , data , o ++ ,
2589+ Py_hexdigits [(ch >> (4 * ndigits )) & 0xf ]);
2590+ }
2591+ break ;
2592+ }
2593+ }
2594+ writer -> pos = o ;
2595+ }
2596+
25552597/* Escape special and non-printable characters like repr() does, but
2556- without surrounding quotes. If the F_SIGN flag is set, also escape
2557- all non-ASCII characters. Characters are escaped with "\uHHHH" and
2558- "\UHHHHHHHH", raw bytes (see F_RAWBYTES) -- with "\xHH".
2559- If precision is non-negative, only the first precision characters of
2560- str are escaped and returned. */
2561- static PyObject *
2562- unicode_fromformat_escape (PyObject * str , Py_ssize_t precision , int flags )
2598+ without surrounding quotes, and write the result to the writer.
2599+ If the F_SIGN flag is set, also escape all non-ASCII characters.
2600+ Characters are escaped with "\uHHHH" and "\UHHHHHHHH", raw bytes
2601+ (see F_RAWBYTES) -- with "\xHH".
2602+ The precision applies to the original string, the width -- to the
2603+ escaped one. */
2604+ static int
2605+ unicode_fromformat_write_escaped (_PyUnicodeWriter * writer , PyObject * str ,
2606+ Py_ssize_t width , Py_ssize_t precision ,
2607+ int flags )
25632608{
25642609 Py_ssize_t isize = PyUnicode_GET_LENGTH (str );
25652610 const void * idata = PyUnicode_DATA (str );
@@ -2568,7 +2613,7 @@ unicode_fromformat_escape(PyObject *str, Py_ssize_t precision, int flags)
25682613 isize = precision ;
25692614 }
25702615
2571- /* Compute the length and the maximum character of the output */
2616+ /* Compute the length and the maximum character of the escaped string */
25722617 Py_ssize_t osize = 0 ;
25732618 Py_UCS4 maxch = 127 ;
25742619 for (Py_ssize_t i = 0 ; i < isize ; i ++ ) {
@@ -2579,56 +2624,36 @@ unicode_fromformat_escape(PyObject *str, Py_ssize_t precision, int flags)
25792624 }
25802625 if (osize > PY_SSIZE_T_MAX - incr ) {
25812626 PyErr_SetString (PyExc_OverflowError , "string is too long" );
2582- return NULL ;
2627+ return -1 ;
25832628 }
25842629 osize += incr ;
25852630 }
25862631
2587- PyObject * res = PyUnicode_New (osize , maxch );
2588- if (res == NULL ) {
2589- return NULL ;
2632+ if (_PyUnicodeWriter_Prepare (writer , Py_MAX (osize , width ), maxch ) == -1 )
2633+ return -1 ;
2634+
2635+ Py_ssize_t fill = Py_MAX (width - osize , 0 );
2636+ if (fill && !(flags & F_LJUST )) {
2637+ if (PyUnicode_Fill (writer -> buffer , writer -> pos , fill , ' ' ) == -1 )
2638+ return -1 ;
2639+ writer -> pos += fill ;
25902640 }
2591- int okind = PyUnicode_KIND (res );
2592- void * odata = PyUnicode_DATA (res );
25932641
2594- Py_ssize_t o = 0 ;
2642+ Py_ssize_t start = writer -> pos ;
25952643 for (Py_ssize_t i = 0 ; i < isize ; i ++ ) {
25962644 Py_UCS4 ch = PyUnicode_READ (ikind , idata , i );
2597- switch (escaped_char_size (ch , flags )) {
2598- case 1 :
2599- PyUnicode_WRITE (okind , odata , o ++ , ch );
2600- break ;
2601- case 2 :
2602- PyUnicode_WRITE (okind , odata , o ++ , '\\' );
2603- switch (ch ) {
2604- case '\t' : ch = 't' ; break ;
2605- case '\r' : ch = 'r' ; break ;
2606- case '\n' : ch = 'n' ; break ;
2607- }
2608- PyUnicode_WRITE (okind , odata , o ++ , ch );
2609- break ;
2610- case 4 :
2611- PyUnicode_WRITE (okind , odata , o ++ , '\\' );
2612- PyUnicode_WRITE (okind , odata , o ++ , 'x' );
2613- PyUnicode_WRITE (okind , odata , o ++ , Py_hexdigits [(ch >> 4 ) & 0xf ]);
2614- PyUnicode_WRITE (okind , odata , o ++ , Py_hexdigits [ch & 0xf ]);
2615- break ;
2616- default :
2617- {
2618- int ndigits = (ch < 0x10000 ) ? 4 : 8 ;
2619- PyUnicode_WRITE (okind , odata , o ++ , '\\' );
2620- PyUnicode_WRITE (okind , odata , o ++ , (ch < 0x10000 ) ? 'u' : 'U' );
2621- while (-- ndigits >= 0 ) {
2622- PyUnicode_WRITE (okind , odata , o ++ ,
2623- Py_hexdigits [(ch >> (4 * ndigits )) & 0xf ]);
2624- }
2625- break ;
2626- }
2627- }
2645+ unicode_write_escaped_char (writer , ch , flags );
26282646 }
2629- assert (o == osize );
2630- assert (_PyUnicode_CheckConsistency (res , 1 ));
2631- return res ;
2647+ assert (writer -> pos - start == osize );
2648+ (void )start ;
2649+
2650+ if (fill && (flags & F_LJUST )) {
2651+ if (PyUnicode_Fill (writer -> buffer , writer -> pos , fill , ' ' ) == -1 )
2652+ return -1 ;
2653+ writer -> pos += fill ;
2654+ }
2655+
2656+ return 0 ;
26322657}
26332658
26342659static int
@@ -2639,15 +2664,8 @@ unicode_fromformat_write_str(_PyUnicodeWriter *writer, PyObject *str,
26392664 Py_UCS4 maxchar ;
26402665
26412666 if (flags & F_ESCAPE ) {
2642- /* The precision applies to the original string,
2643- the width -- to the escaped one. */
2644- PyObject * escaped = unicode_fromformat_escape (str , precision , flags );
2645- if (escaped == NULL )
2646- return -1 ;
2647- int res = unicode_fromformat_write_str (writer , escaped , width , -1 ,
2648- flags & ~F_ESCAPE );
2649- Py_DECREF (escaped );
2650- return res ;
2667+ return unicode_fromformat_write_escaped (writer , str , width , precision ,
2668+ flags );
26512669 }
26522670
26532671 length = PyUnicode_GET_LENGTH (str );
@@ -2915,13 +2933,11 @@ unicode_fromformat_arg(_PyUnicodeWriter *writer,
29152933 return NULL ;
29162934 }
29172935 if (flags & F_ESCAPE ) {
2918- PyObject * str = PyUnicode_FromOrdinal (ordinal );
2919- if (str == NULL )
2920- return NULL ;
2921- int res = unicode_fromformat_write_str (writer , str , -1 , -1 , flags );
2922- Py_DECREF (str );
2923- if (res < 0 )
2936+ Py_ssize_t len = escaped_char_size (ordinal , flags );
2937+ Py_UCS4 maxch = (len == 1 ) ? (Py_UCS4 )ordinal : 127 ;
2938+ if (_PyUnicodeWriter_Prepare (writer , len , maxch ) < 0 )
29242939 return NULL ;
2940+ unicode_write_escaped_char (writer , ordinal , flags );
29252941 }
29262942 else if (_PyUnicodeWriter_WriteCharInline (writer , ordinal ) < 0 )
29272943 return NULL ;
0 commit comments