summaryrefslogtreecommitdiffstats
path: root/Objects/dictobject.c
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2013-11-19 12:07:38 (GMT)
committerVictor Stinner <victor.stinner@gmail.com>2013-11-19 12:07:38 (GMT)
commitf91929b1d855d491cf5d4aba88c9a8757b401411 (patch)
tree468ec2640ae8ee8be449b4936845ffe2b16b08e6 /Objects/dictobject.c
parent88a9cd9b57cff15b47d3aecddf56535eb32769fc (diff)
downloadcpython-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.c109
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