@@ -26,6 +26,19 @@ static PyStringObject *nullstring;
2626static PyObject * interned ;
2727
2828
29+ #if defined(HAVE_MBTOWC ) && defined(HAVE_WCHAR_H )
30+ # define PRINT_MULTIBYTE_STRING
31+ # include <locale.h>
32+ # include <wchar.h>
33+ # if defined(HAVE_ISWPRINT )
34+ # define _isprint iswprint
35+ # else
36+ # define _isprint isprint
37+ # endif
38+ #endif
39+
40+ static const char * hexchars = "0123456789abcdef" ;
41+
2942/*
3043 For both PyString_FromString() and PyString_FromStringAndSize(), the
3144 parameter `size' denotes number of characters to allocate, not counting any
@@ -749,8 +762,14 @@ PyString_AsStringAndSize(register PyObject *obj,
749762static int
750763string_print (PyStringObject * op , FILE * fp , int flags )
751764{
765+ #ifndef PRINT_MULTIBYTE_STRING
752766 int i ;
753767 char c ;
768+ #else
769+ char * scur , * send ;
770+ wchar_t c ;
771+ int cr ;
772+ #endif
754773 int quote ;
755774
756775 /* XXX Ought to check for interrupts when writing long strings */
@@ -776,20 +795,36 @@ string_print(PyStringObject *op, FILE *fp, int flags)
776795 quote = '"' ;
777796
778797 fputc (quote , fp );
798+ #ifndef PRINT_MULTIBYTE_STRING
779799 for (i = 0 ; i < op -> ob_size ; i ++ ) {
780800 c = op -> ob_sval [i ];
801+ #else
802+ for (scur = op -> ob_sval , send = op -> ob_sval + op -> ob_size ;
803+ scur < send ; scur += cr ) {
804+ if ((cr = mbtowc (& c , scur , send - scur )) <= 0 )
805+ goto non_printable ;
806+ #endif
781807 if (c == quote || c == '\\' )
782- fprintf ( fp , "\\%c" , c );
808+ fputc ( '\\' , fp ), fputc ( c , fp );
783809 else if (c == '\t' )
784- fprintf ( fp , "\\t" );
810+ fputs ( "\\t" , fp );
785811 else if (c == '\n' )
786- fprintf ( fp , "\\n" );
812+ fputs ( "\\n" , fp );
787813 else if (c == '\r' )
788- fprintf (fp , "\\r" );
789- else if (c < ' ' || c >= 0x7f )
790- fprintf (fp , "\\x%02x" , c & 0xff );
791- else
814+ fputs ("\\r" , fp );
815+ #ifndef PRINT_MULTIBYTE_STRING
816+ else if (' ' <= c && c < 0x7f)
792817 fputc (c , fp );
818+ else
819+ fprintf (fp , "\\x %02 x ", c & 0xff );
820+ #else
821+ else if (_isprint (c ))
822+ fwrite (scur , cr , 1 , fp );
823+ else {
824+ non_printable : cr = 1 ; /* unit to move cursor */
825+ fprintf (fp , "\\x%02x" , * scur & 0xff );
826+ }
827+ #endif
793828 }
794829 fputc (quote , fp );
795830 return 0 ;
@@ -810,8 +845,14 @@ PyString_Repr(PyObject *obj, int smartquotes)
810845 return NULL ;
811846 }
812847 else {
848+ #ifndef PRINT_MULTIBYTE_STRING
813849 register int i ;
814850 register char c ;
851+ #else
852+ register char * scur , * send ;
853+ wchar_t c ;
854+ int cr ;
855+ #endif
815856 register char * p ;
816857 int quote ;
817858
@@ -824,11 +865,18 @@ PyString_Repr(PyObject *obj, int smartquotes)
824865
825866 p = PyString_AS_STRING (v );
826867 * p ++ = quote ;
868+ #ifndef PRINT_MULTIBYTE_STRING
827869 for (i = 0 ; i < op -> ob_size ; i ++ ) {
828870 /* There's at least enough room for a hex escape
829871 and a closing quote. */
830872 assert (newsize - (p - PyString_AS_STRING (v )) >= 5 );
831873 c = op -> ob_sval [i ];
874+ #else
875+ for (scur = op -> ob_sval , send = op -> ob_sval + op -> ob_size ;
876+ scur < send ; scur += cr ) {
877+ if ((cr = mbtowc (& c , scur , send - scur )) <= 0 )
878+ goto non_printable ;
879+ #endif
832880 if (c == quote || c == '\\' )
833881 * p ++ = '\\' , * p ++ = c ;
834882 else if (c == '\t' )
@@ -837,15 +885,20 @@ PyString_Repr(PyObject *obj, int smartquotes)
837885 * p ++ = '\\' , * p ++ = 'n' ;
838886 else if (c == '\r' )
839887 * p ++ = '\\' , * p ++ = 'r' ;
840- else if (c < ' ' || c >= 0x7f ) {
841- /* For performance, we don't want to call
842- PyOS_snprintf here (extra layers of
843- function call). */
844- sprintf (p , "\\x%02x" , c & 0xff );
845- p += 4 ;
846- }
847- else
888+ #ifndef PRINT_MULTIBYTE_STRING
889+ else if (' ' <= c && c < 0x7f)
848890 * p ++ = c ;
891+ else {
892+ #else
893+ else if (_isprint (c ))
894+ memcpy (p , scur , cr ), p += cr ;
895+ else {
896+ non_printable : cr = 1 ; c = * scur ;
897+ #endif
898+ * p ++ = '\\' ; * p ++ = 'x' ;
899+ * p ++ = hexchars [(c >> 4 ) & 0x0f ];
900+ * p ++ = hexchars [c & 0x0f ];
901+ }
849902 }
850903 assert (newsize - (p - PyString_AS_STRING (v )) >= 1 );
851904 * p ++ = quote ;
0 commit comments