diff --git a/Include/internal/pycore_bytesobject.h b/Include/internal/pycore_bytesobject.h index 6c6e2ed21e3761..c7bc53b6073770 100644 --- a/Include/internal/pycore_bytesobject.h +++ b/Include/internal/pycore_bytesobject.h @@ -73,6 +73,26 @@ struct PyBytesWriter { // Export for '_testcapi' shared extension PyAPI_FUNC(PyBytesWriter*) _PyBytesWriter_CreateByteArray(Py_ssize_t size); +static inline Py_ssize_t +_PyBytesWriter_GetSize(PyBytesWriter *writer) +{ + return writer->size; +} + +static inline char* +_PyBytesWriter_GetData(PyBytesWriter *writer) +{ + if (writer->obj == NULL) { + return writer->small_buffer; + } + else if (writer->use_bytearray) { + return PyByteArray_AS_STRING(writer->obj); + } + else { + return PyBytes_AS_STRING(writer->obj); + } +} + #ifdef __cplusplus } #endif diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index 91d20cb9afa7ba..de8ab26db1e966 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -3480,15 +3480,7 @@ _PyBytes_Repeat(char* dest, Py_ssize_t len_dest, static inline char* byteswriter_data(PyBytesWriter *writer) { - if (writer->obj == NULL) { - return writer->small_buffer; - } - else if (writer->use_bytearray) { - return PyByteArray_AS_STRING(writer->obj); - } - else { - return PyBytes_AS_STRING(writer->obj); - } + return _PyBytesWriter_GetData(writer); } @@ -3710,7 +3702,7 @@ PyBytesWriter_GetData(PyBytesWriter *writer) Py_ssize_t PyBytesWriter_GetSize(PyBytesWriter *writer) { - return writer->size; + return _PyBytesWriter_GetSize(writer); } diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 5799d92211aa97..2714df329d32bb 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -8842,15 +8842,13 @@ charmapencode_lookup(Py_UCS4 c, PyObject *mapping, unsigned char *replace) } static int -charmapencode_resize(PyObject **outobj, Py_ssize_t *outpos, Py_ssize_t requiredsize) +charmapencode_resize(PyBytesWriter *writer, Py_ssize_t *outpos, Py_ssize_t requiredsize) { - Py_ssize_t outsize = PyBytes_GET_SIZE(*outobj); + Py_ssize_t outsize = PyBytesWriter_GetSize(writer); /* exponentially overallocate to minimize reallocations */ - if (requiredsize < 2*outsize) - requiredsize = 2*outsize; - if (_PyBytes_Resize(outobj, requiredsize)) - return -1; - return 0; + if (requiredsize < 2 * outsize) + requiredsize = 2 * outsize; + return PyBytesWriter_Resize(writer, requiredsize); } typedef enum charmapencode_result { @@ -8864,12 +8862,12 @@ typedef enum charmapencode_result { reallocation error occurred. The caller must decref the result */ static charmapencode_result charmapencode_output(Py_UCS4 c, PyObject *mapping, - PyObject **outobj, Py_ssize_t *outpos) + PyBytesWriter *writer, Py_ssize_t *outpos) { PyObject *rep; unsigned char replace; char *outstart; - Py_ssize_t outsize = PyBytes_GET_SIZE(*outobj); + Py_ssize_t outsize = _PyBytesWriter_GetSize(writer); if (Py_IS_TYPE(mapping, &EncodingMapType)) { int res = encoding_map_lookup(c, mapping); @@ -8877,9 +8875,9 @@ charmapencode_output(Py_UCS4 c, PyObject *mapping, if (res == -1) return enc_FAILED; if (outsize outsize) /* Make room for all additional bytes. */ - if (charmapencode_resize(res, respos, requiredsize)) { + if (charmapencode_resize(writer, respos, requiredsize)) { Py_DECREF(repunicode); return -1; } - memcpy(PyBytes_AsString(*res) + *respos, + memcpy((char*)PyBytesWriter_GetData(writer) + *respos, PyBytes_AsString(repunicode), repsize); *respos += repsize; *inpos = newpos; @@ -9045,7 +9043,7 @@ charmap_encoding_error( kind = PyUnicode_KIND(repunicode); for (index = 0; index < repsize; index++) { Py_UCS4 repch = PyUnicode_READ(kind, data, index); - x = charmapencode_output(repch, mapping, res, respos); + x = charmapencode_output(repch, mapping, writer, respos); if (x==enc_EXCEPTION) { Py_DECREF(repunicode); return -1; @@ -9067,65 +9065,64 @@ _PyUnicode_EncodeCharmap(PyObject *unicode, PyObject *mapping, const char *errors) { - /* output object */ - PyObject *res = NULL; - /* current input position */ - Py_ssize_t inpos = 0; - Py_ssize_t size; - /* current output position */ - Py_ssize_t respos = 0; - PyObject *error_handler_obj = NULL; - PyObject *exc = NULL; - _Py_error_handler error_handler = _Py_ERROR_UNKNOWN; - const void *data; - int kind; - - size = PyUnicode_GET_LENGTH(unicode); - data = PyUnicode_DATA(unicode); - kind = PyUnicode_KIND(unicode); - /* Default to Latin-1 */ - if (mapping == NULL) + if (mapping == NULL) { return unicode_encode_ucs1(unicode, errors, 256); + } + + Py_ssize_t size = PyUnicode_GET_LENGTH(unicode); + if (size == 0) { + return Py_GetConstant(Py_CONSTANT_EMPTY_BYTES); + } + const void *data = PyUnicode_DATA(unicode); + int kind = PyUnicode_KIND(unicode); + PyObject *error_handler_obj = NULL; + PyObject *exc = NULL; + + /* output object */ + PyBytesWriter *writer; /* allocate enough for a simple encoding without replacements, if we need more, we'll resize */ - res = PyBytes_FromStringAndSize(NULL, size); - if (res == NULL) + writer = PyBytesWriter_Create(size); + if (writer == NULL) { goto onError; - if (size == 0) - return res; + } + + /* current input position */ + Py_ssize_t inpos = 0; + /* current output position */ + Py_ssize_t respos = 0; + _Py_error_handler error_handler = _Py_ERROR_UNKNOWN; while (inpos adjust input position */ ++inpos; + } } - /* Resize if we allocated to much */ - if (respos