From ad7715891e3c6c51b4860e0d496843ee5417206b Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 9 Oct 2015 12:38:53 +0200 Subject: _PyBytesWriter: simplify code to avoid "prealloc" parameters Substract preallocate bytes from min_size before calling _PyBytesWriter_Prepare(). --- Objects/bytesobject.c | 16 ++++++------- Objects/stringlib/codecs.h | 20 +++++++++------- Objects/unicodeobject.c | 58 ++++++++++++++++++++++------------------------ 3 files changed, 47 insertions(+), 47 deletions(-) diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index 4a0735f..075edf8 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -411,8 +411,7 @@ getnextarg(PyObject *args, Py_ssize_t arglen, Py_ssize_t *p_argidx) static char* formatfloat(PyObject *v, int flags, int prec, int type, - PyObject **p_result, _PyBytesWriter *writer, char *str, - Py_ssize_t prealloc) + PyObject **p_result, _PyBytesWriter *writer, char *str) { char *p; PyObject *result; @@ -437,11 +436,9 @@ formatfloat(PyObject *v, int flags, int prec, int type, len = strlen(p); if (writer != NULL) { - if ((Py_ssize_t)len > prealloc) { - str = _PyBytesWriter_Prepare(writer, str, len - prealloc); - if (str == NULL) - return NULL; - } + str = _PyBytesWriter_Prepare(writer, str, len); + if (str == NULL) + return NULL; Py_MEMCPY(str, p, len); str += len; return str; @@ -865,13 +862,14 @@ _PyBytes_Format(PyObject *format, PyObject *args) && !(flags & (F_SIGN | F_BLANK))) { /* Fast path */ - res = formatfloat(v, flags, prec, c, NULL, &writer, res, 1); + writer.min_size -= 2; /* size preallocated by "%f" */ + res = formatfloat(v, flags, prec, c, NULL, &writer, res); if (res == NULL) goto error; continue; } - if (!formatfloat(v, flags, prec, c, &temp, NULL, res, 1)) + if (!formatfloat(v, flags, prec, c, &temp, NULL, res)) goto error; pbuf = PyBytes_AS_STRING(temp); len = PyBytes_GET_SIZE(temp); diff --git a/Objects/stringlib/codecs.h b/Objects/stringlib/codecs.h index ae99d1a..6842f67 100644 --- a/Objects/stringlib/codecs.h +++ b/Objects/stringlib/codecs.h @@ -345,7 +345,9 @@ STRINGLIB(utf8_encoder)(PyObject *unicode, break; case _Py_ERROR_BACKSLASHREPLACE: - p = backslashreplace(&writer, max_char_size, p, + /* substract preallocated bytes */ + writer.min_size -= max_char_size * (endpos - startpos); + p = backslashreplace(&writer, p, unicode, startpos, endpos); if (p == NULL) goto error; @@ -353,7 +355,9 @@ STRINGLIB(utf8_encoder)(PyObject *unicode, break; case _Py_ERROR_XMLCHARREFREPLACE: - p = xmlcharrefreplace(&writer, max_char_size, p, + /* substract preallocated bytes */ + writer.min_size -= max_char_size * (endpos - startpos); + p = xmlcharrefreplace(&writer, p, unicode, startpos, endpos); if (p == NULL) goto error; @@ -381,17 +385,17 @@ STRINGLIB(utf8_encoder)(PyObject *unicode, if (!rep) goto error; + /* substract preallocated bytes */ + writer.min_size -= max_char_size; + if (PyBytes_Check(rep)) repsize = PyBytes_GET_SIZE(rep); else repsize = PyUnicode_GET_LENGTH(rep); - if (repsize > max_char_size) { - p = _PyBytesWriter_Prepare(&writer, p, - repsize - max_char_size); - if (p == NULL) - goto error; - } + p = _PyBytesWriter_Prepare(&writer, p, repsize); + if (p == NULL) + goto error; if (PyBytes_Check(rep)) { memcpy(p, PyBytes_AS_STRING(rep), repsize); diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index a3bbf92..0bcacd8 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -565,11 +565,10 @@ unicode_result_unchanged(PyObject *unicode) /* Implementation of the "backslashreplace" error handler for 8-bit encodings: ASCII, Latin1, UTF-8, etc. */ static char* -backslashreplace(_PyBytesWriter *writer, Py_ssize_t prealloc_per_char, - char *str, +backslashreplace(_PyBytesWriter *writer, char *str, PyObject *unicode, Py_ssize_t collstart, Py_ssize_t collend) { - Py_ssize_t size, i, prealloc; + Py_ssize_t size, i; Py_UCS4 ch; enum PyUnicode_Kind kind; void *data; @@ -600,12 +599,9 @@ backslashreplace(_PyBytesWriter *writer, Py_ssize_t prealloc_per_char, size += incr; } - prealloc = prealloc_per_char * (collend - collstart); - if (size > prealloc) { - str = _PyBytesWriter_Prepare(writer, str, size - prealloc); - if (str == NULL) - return NULL; - } + str = _PyBytesWriter_Prepare(writer, str, size); + if (str == NULL) + return NULL; /* generate replacement */ for (i = collstart; i < collend; ++i) { @@ -636,11 +632,10 @@ backslashreplace(_PyBytesWriter *writer, Py_ssize_t prealloc_per_char, /* Implementation of the "xmlcharrefreplace" error handler for 8-bit encodings: ASCII, Latin1, UTF-8, etc. */ static char* -xmlcharrefreplace(_PyBytesWriter *writer, Py_ssize_t prealloc_per_char, - char *str, +xmlcharrefreplace(_PyBytesWriter *writer, char *str, PyObject *unicode, Py_ssize_t collstart, Py_ssize_t collend) { - Py_ssize_t size, i, prealloc; + Py_ssize_t size, i; Py_UCS4 ch; enum PyUnicode_Kind kind; void *data; @@ -679,12 +674,9 @@ xmlcharrefreplace(_PyBytesWriter *writer, Py_ssize_t prealloc_per_char, size += incr; } - prealloc = prealloc_per_char * (collend - collstart); - if (size > prealloc) { - str = _PyBytesWriter_Prepare(writer, str, size - prealloc); - if (str == NULL) - return NULL; - } + str = _PyBytesWriter_Prepare(writer, str, size); + if (str == NULL) + return NULL; /* generate replacement */ for (i = collstart; i < collend; ++i) { @@ -6666,7 +6658,9 @@ unicode_encode_ucs1(PyObject *unicode, break; case _Py_ERROR_BACKSLASHREPLACE: - str = backslashreplace(&writer, 1, str, + /* substract preallocated bytes */ + writer.min_size -= (collend - collstart); + str = backslashreplace(&writer, str, unicode, collstart, collend); if (str == NULL) goto onError; @@ -6674,7 +6668,9 @@ unicode_encode_ucs1(PyObject *unicode, break; case _Py_ERROR_XMLCHARREFREPLACE: - str = xmlcharrefreplace(&writer, 1, str, + /* substract preallocated bytes */ + writer.min_size -= (collend - collstart); + str = xmlcharrefreplace(&writer, str, unicode, collstart, collend); if (str == NULL) goto onError; @@ -6705,14 +6701,17 @@ unicode_encode_ucs1(PyObject *unicode, PyUnicode_READY(repunicode) == -1)) goto onError; + /* substract preallocated bytes */ + writer.min_size -= 1; + if (PyBytes_Check(repunicode)) { /* Directly copy bytes result to output. */ repsize = PyBytes_Size(repunicode); - if (repsize > 1) { - str = _PyBytesWriter_Prepare(&writer, str, repsize-1); - if (str == NULL) - goto onError; - } + + str = _PyBytesWriter_Prepare(&writer, str, repsize); + if (str == NULL) + goto onError; + memcpy(str, PyBytes_AsString(repunicode), repsize); str += repsize; pos = newpos; @@ -6724,11 +6723,10 @@ unicode_encode_ucs1(PyObject *unicode, have+the replacement+the rest of the string, so we won't have to check space for encodable characters) */ repsize = PyUnicode_GET_LENGTH(repunicode); - if (repsize > 1) { - str = _PyBytesWriter_Prepare(&writer, str, repsize-1); - if (str == NULL) - goto onError; - } + + str = _PyBytesWriter_Prepare(&writer, str, repsize); + if (str == NULL) + goto onError; /* check if there is anything unencodable in the replacement and copy it to the output */ -- cgit v0.12