@@ -8842,15 +8842,13 @@ charmapencode_lookup(Py_UCS4 c, PyObject *mapping, unsigned char *replace)
88428842}
88438843
88448844static int
8845- charmapencode_resize (PyObject * * outobj , Py_ssize_t * outpos , Py_ssize_t requiredsize )
8845+ charmapencode_resize (PyBytesWriter * writer , Py_ssize_t * outpos , Py_ssize_t requiredsize )
88468846{
8847- Py_ssize_t outsize = PyBytes_GET_SIZE ( * outobj );
8847+ Py_ssize_t outsize = PyBytesWriter_GetSize ( writer );
88488848 /* exponentially overallocate to minimize reallocations */
8849- if (requiredsize < 2 * outsize )
8850- requiredsize = 2 * outsize ;
8851- if (_PyBytes_Resize (outobj , requiredsize ))
8852- return -1 ;
8853- return 0 ;
8849+ if (requiredsize < 2 * outsize )
8850+ requiredsize = 2 * outsize ;
8851+ return PyBytesWriter_Resize (writer , requiredsize );
88548852}
88558853
88568854typedef enum charmapencode_result {
@@ -8864,22 +8862,22 @@ typedef enum charmapencode_result {
88648862 reallocation error occurred. The caller must decref the result */
88658863static charmapencode_result
88668864charmapencode_output (Py_UCS4 c , PyObject * mapping ,
8867- PyObject * * outobj , Py_ssize_t * outpos )
8865+ PyBytesWriter * writer , Py_ssize_t * outpos )
88688866{
88698867 PyObject * rep ;
88708868 unsigned char replace ;
88718869 char * outstart ;
8872- Py_ssize_t outsize = PyBytes_GET_SIZE ( * outobj );
8870+ Py_ssize_t outsize = PyBytesWriter_GetSize ( writer );
88738871
88748872 if (Py_IS_TYPE (mapping , & EncodingMapType )) {
88758873 int res = encoding_map_lookup (c , mapping );
88768874 Py_ssize_t requiredsize = * outpos + 1 ;
88778875 if (res == -1 )
88788876 return enc_FAILED ;
88798877 if (outsize < requiredsize )
8880- if (charmapencode_resize (outobj , outpos , requiredsize ))
8878+ if (charmapencode_resize (writer , outpos , requiredsize ))
88818879 return enc_EXCEPTION ;
8882- outstart = PyBytes_AS_STRING ( * outobj );
8880+ outstart = PyBytesWriter_GetData ( writer );
88838881 outstart [(* outpos )++ ] = (char )res ;
88848882 return enc_SUCCESS ;
88858883 }
@@ -8894,23 +8892,23 @@ charmapencode_output(Py_UCS4 c, PyObject *mapping,
88948892 if (PyLong_Check (rep )) {
88958893 Py_ssize_t requiredsize = * outpos + 1 ;
88968894 if (outsize < requiredsize )
8897- if (charmapencode_resize (outobj , outpos , requiredsize )) {
8895+ if (charmapencode_resize (writer , outpos , requiredsize )) {
88988896 Py_DECREF (rep );
88998897 return enc_EXCEPTION ;
89008898 }
8901- outstart = PyBytes_AS_STRING ( * outobj );
8899+ outstart = PyBytesWriter_GetData ( writer );
89028900 outstart [(* outpos )++ ] = (char )replace ;
89038901 }
89048902 else {
89058903 const char * repchars = PyBytes_AS_STRING (rep );
89068904 Py_ssize_t repsize = PyBytes_GET_SIZE (rep );
89078905 Py_ssize_t requiredsize = * outpos + repsize ;
89088906 if (outsize < requiredsize )
8909- if (charmapencode_resize (outobj , outpos , requiredsize )) {
8907+ if (charmapencode_resize (writer , outpos , requiredsize )) {
89108908 Py_DECREF (rep );
89118909 return enc_EXCEPTION ;
89128910 }
8913- outstart = PyBytes_AS_STRING ( * outobj );
8911+ outstart = PyBytesWriter_GetData ( writer );
89148912 memcpy (outstart + * outpos , repchars , repsize );
89158913 * outpos += repsize ;
89168914 }
@@ -8926,7 +8924,7 @@ charmap_encoding_error(
89268924 PyObject * unicode , Py_ssize_t * inpos , PyObject * mapping ,
89278925 PyObject * * exceptionObject ,
89288926 _Py_error_handler * error_handler , PyObject * * error_handler_obj , const char * errors ,
8929- PyObject * * res , Py_ssize_t * respos )
8927+ PyBytesWriter * writer , Py_ssize_t * respos )
89308928{
89318929 PyObject * repunicode = NULL ; /* initialize to prevent gcc warning */
89328930 Py_ssize_t size , repsize ;
@@ -8981,7 +8979,7 @@ charmap_encoding_error(
89818979
89828980 case _Py_ERROR_REPLACE :
89838981 for (collpos = collstartpos ; collpos < collendpos ; ++ collpos ) {
8984- x = charmapencode_output ('?' , mapping , res , respos );
8982+ x = charmapencode_output ('?' , mapping , writer , respos );
89858983 if (x == enc_EXCEPTION ) {
89868984 return -1 ;
89878985 }
@@ -9002,7 +9000,7 @@ charmap_encoding_error(
90029000 char * cp ;
90039001 sprintf (buffer , "&#%d;" , (int )PyUnicode_READ_CHAR (unicode , collpos ));
90049002 for (cp = buffer ; * cp ; ++ cp ) {
9005- x = charmapencode_output (* cp , mapping , res , respos );
9003+ x = charmapencode_output (* cp , mapping , writer , respos );
90069004 if (x == enc_EXCEPTION )
90079005 return -1 ;
90089006 else if (x == enc_FAILED ) {
@@ -9022,17 +9020,17 @@ charmap_encoding_error(
90229020 return -1 ;
90239021 if (PyBytes_Check (repunicode )) {
90249022 /* Directly copy bytes result to output. */
9025- Py_ssize_t outsize = PyBytes_Size ( * res );
9023+ Py_ssize_t outsize = PyBytesWriter_GetSize ( writer );
90269024 Py_ssize_t requiredsize ;
90279025 repsize = PyBytes_Size (repunicode );
90289026 requiredsize = * respos + repsize ;
90299027 if (requiredsize > outsize )
90309028 /* Make room for all additional bytes. */
9031- if (charmapencode_resize (res , respos , requiredsize )) {
9029+ if (charmapencode_resize (writer , respos , requiredsize )) {
90329030 Py_DECREF (repunicode );
90339031 return -1 ;
90349032 }
9035- memcpy (PyBytes_AsString ( * res ) + * respos ,
9033+ memcpy (PyBytesWriter_GetData ( writer ) + * respos ,
90369034 PyBytes_AsString (repunicode ), repsize );
90379035 * respos += repsize ;
90389036 * inpos = newpos ;
@@ -9045,7 +9043,7 @@ charmap_encoding_error(
90459043 kind = PyUnicode_KIND (repunicode );
90469044 for (index = 0 ; index < repsize ; index ++ ) {
90479045 Py_UCS4 repch = PyUnicode_READ (kind , data , index );
9048- x = charmapencode_output (repch , mapping , res , respos );
9046+ x = charmapencode_output (repch , mapping , writer , respos );
90499047 if (x == enc_EXCEPTION ) {
90509048 Py_DECREF (repunicode );
90519049 return -1 ;
@@ -9067,65 +9065,63 @@ _PyUnicode_EncodeCharmap(PyObject *unicode,
90679065 PyObject * mapping ,
90689066 const char * errors )
90699067{
9068+ /* Default to Latin-1 */
9069+ if (mapping == NULL ) {
9070+ return unicode_encode_ucs1 (unicode , errors , 256 );
9071+ }
9072+
9073+ Py_ssize_t size = PyUnicode_GET_LENGTH (unicode );
9074+ if (size == 0 ) {
9075+ return Py_GetConstant (Py_CONSTANT_EMPTY_BYTES );
9076+ }
9077+ const void * data = PyUnicode_DATA (unicode );
9078+ int kind = PyUnicode_KIND (unicode );
9079+
90709080 /* output object */
9071- PyObject * res = NULL ;
9081+ PyBytesWriter * writer ;
9082+ /* allocate enough for a simple encoding without
9083+ replacements, if we need more, we'll resize */
9084+ writer = PyBytesWriter_Create (size );
9085+ if (writer == NULL ) {
9086+ goto onError ;
9087+ }
9088+
90729089 /* current input position */
90739090 Py_ssize_t inpos = 0 ;
9074- Py_ssize_t size ;
90759091 /* current output position */
90769092 Py_ssize_t respos = 0 ;
90779093 PyObject * error_handler_obj = NULL ;
90789094 PyObject * exc = NULL ;
90799095 _Py_error_handler error_handler = _Py_ERROR_UNKNOWN ;
9080- const void * data ;
9081- int kind ;
9082-
9083- size = PyUnicode_GET_LENGTH (unicode );
9084- data = PyUnicode_DATA (unicode );
9085- kind = PyUnicode_KIND (unicode );
9086-
9087- /* Default to Latin-1 */
9088- if (mapping == NULL )
9089- return unicode_encode_ucs1 (unicode , errors , 256 );
9090-
9091- /* allocate enough for a simple encoding without
9092- replacements, if we need more, we'll resize */
9093- res = PyBytes_FromStringAndSize (NULL , size );
9094- if (res == NULL )
9095- goto onError ;
9096- if (size == 0 )
9097- return res ;
90989096
90999097 while (inpos < size ) {
91009098 Py_UCS4 ch = PyUnicode_READ (kind , data , inpos );
91019099 /* try to encode it */
9102- charmapencode_result x = charmapencode_output (ch , mapping , & res , & respos );
9100+ charmapencode_result x = charmapencode_output (ch , mapping , writer , & respos );
91039101 if (x == enc_EXCEPTION ) /* error */
91049102 goto onError ;
91059103 if (x == enc_FAILED ) { /* unencodable character */
91069104 if (charmap_encoding_error (unicode , & inpos , mapping ,
91079105 & exc ,
91089106 & error_handler , & error_handler_obj , errors ,
9109- & res , & respos )) {
9107+ writer , & respos )) {
91109108 goto onError ;
91119109 }
91129110 }
9113- else
9111+ else {
91149112 /* done with this character => adjust input position */
91159113 ++ inpos ;
9114+ }
91169115 }
91179116
9118- /* Resize if we allocated to much */
9119- if (respos < PyBytes_GET_SIZE (res ))
9120- if (_PyBytes_Resize (& res , respos ) < 0 )
9121- goto onError ;
9122-
91239117 Py_XDECREF (exc );
91249118 Py_XDECREF (error_handler_obj );
9125- return res ;
9119+
9120+ /* Resize if we allocated too much */
9121+ return PyBytesWriter_FinishWithSize (writer , respos );
91269122
91279123 onError :
9128- Py_XDECREF ( res );
9124+ PyBytesWriter_Discard ( writer );
91299125 Py_XDECREF (exc );
91309126 Py_XDECREF (error_handler_obj );
91319127 return NULL ;
0 commit comments