diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2013-11-19 12:07:38 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2013-11-19 12:07:38 (GMT) |
commit | f91929b1d855d491cf5d4aba88c9a8757b401411 (patch) | |
tree | 468ec2640ae8ee8be449b4936845ffe2b16b08e6 /Objects/dictobject.c | |
parent | 88a9cd9b57cff15b47d3aecddf56535eb32769fc (diff) | |
download | cpython-f91929b1d855d491cf5d4aba88c9a8757b401411.zip cpython-f91929b1d855d491cf5d4aba88c9a8757b401411.tar.gz cpython-f91929b1d855d491cf5d4aba88c9a8757b401411.tar.bz2 |
Issue #19646: repr(dict) now uses _PyUnicodeWriter API for better performances
Diffstat (limited to 'Objects/dictobject.c')
-rw-r--r-- | Objects/dictobject.c | 109 |
1 files changed, 54 insertions, 55 deletions
diff --git a/Objects/dictobject.c b/Objects/dictobject.c index c224052..3c1b3bb 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -1397,9 +1397,9 @@ static PyObject * dict_repr(PyDictObject *mp) { Py_ssize_t i; - PyObject *s, *temp, *colon = NULL; - PyObject *pieces = NULL, *result = NULL; - PyObject *key, *value; + PyObject *key = NULL, *value = NULL; + _PyUnicodeWriter writer; + int first; i = Py_ReprEnter((PyObject *)mp); if (i != 0) { @@ -1407,74 +1407,73 @@ dict_repr(PyDictObject *mp) } if (mp->ma_used == 0) { - result = PyUnicode_FromString("{}"); - goto Done; + Py_ReprLeave((PyObject *)mp); + return PyUnicode_FromString("{}"); } - pieces = PyList_New(0); - if (pieces == NULL) - goto Done; + _PyUnicodeWriter_Init(&writer); + writer.overallocate = 1; + /* "{" + "1: 2" + ", 3: 4" * (len - 1) + "}" */ + writer.min_length = 1 + 4 + (2 + 4) * (mp->ma_used - 1) + 1; - colon = PyUnicode_FromString(": "); - if (colon == NULL) - goto Done; + if (_PyUnicodeWriter_WriteChar(&writer, '{') < 0) + goto error; /* Do repr() on each key+value pair, and insert ": " between them. Note that repr may mutate the dict. */ i = 0; + first = 1; while (PyDict_Next((PyObject *)mp, &i, &key, &value)) { - int status; + PyObject *s; + int res; + /* Prevent repr from deleting key or value during key format. */ Py_INCREF(key); Py_INCREF(value); + + if (!first) { + if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2) < 0) + goto error; + } + first = 0; + s = PyObject_Repr(key); - PyUnicode_Append(&s, colon); if (s == NULL) - goto Done; + goto error; + res = _PyUnicodeWriter_WriteStr(&writer, s); + Py_DECREF(s); + if (res < 0) + goto error; - PyUnicode_AppendAndDel(&s, PyObject_Repr(value)); - Py_DECREF(key); - Py_DECREF(value); + if (_PyUnicodeWriter_WriteASCIIString(&writer, ": ", 2) < 0) + goto error; + + s = PyObject_Repr(value); if (s == NULL) - goto Done; - status = PyList_Append(pieces, s); - Py_DECREF(s); /* append created a new ref */ - if (status < 0) - goto Done; - } - - /* Add "{}" decorations to the first and last items. */ - assert(PyList_GET_SIZE(pieces) > 0); - s = PyUnicode_FromString("{"); - if (s == NULL) - goto Done; - temp = PyList_GET_ITEM(pieces, 0); - PyUnicode_AppendAndDel(&s, temp); - PyList_SET_ITEM(pieces, 0, s); - if (s == NULL) - goto Done; - - s = PyUnicode_FromString("}"); - if (s == NULL) - goto Done; - temp = PyList_GET_ITEM(pieces, PyList_GET_SIZE(pieces) - 1); - PyUnicode_AppendAndDel(&temp, s); - PyList_SET_ITEM(pieces, PyList_GET_SIZE(pieces) - 1, temp); - if (temp == NULL) - goto Done; - - /* Paste them all together with ", " between. */ - s = PyUnicode_FromString(", "); - if (s == NULL) - goto Done; - result = PyUnicode_Join(s, pieces); - Py_DECREF(s); - -Done: - Py_XDECREF(pieces); - Py_XDECREF(colon); + goto error; + res = _PyUnicodeWriter_WriteStr(&writer, s); + Py_DECREF(s); + if (res < 0) + goto error; + + Py_CLEAR(key); + Py_CLEAR(value); + } + + writer.overallocate = 0; + if (_PyUnicodeWriter_WriteChar(&writer, '}') < 0) + goto error; + Py_ReprLeave((PyObject *)mp); - return result; + + return _PyUnicodeWriter_Finish(&writer); + +error: + Py_ReprLeave((PyObject *)mp); + _PyUnicodeWriter_Dealloc(&writer); + Py_XDECREF(key); + Py_XDECREF(value); + return NULL; } static Py_ssize_t |