diff options
author | Tim Peters <tim.peters@gmail.com> | 2001-06-16 05:11:17 (GMT) |
---|---|---|
committer | Tim Peters <tim.peters@gmail.com> | 2001-06-16 05:11:17 (GMT) |
commit | a7259597f1f9ef389012010d7b8a02ebcf7396e7 (patch) | |
tree | 7ada9cc6a3f30bc41999ba56da018ccd55342df8 /Objects | |
parent | 239508cd1087a521ebe40fabc96c66dcb11c3f8c (diff) | |
download | cpython-a7259597f1f9ef389012010d7b8a02ebcf7396e7.zip cpython-a7259597f1f9ef389012010d7b8a02ebcf7396e7.tar.gz cpython-a7259597f1f9ef389012010d7b8a02ebcf7396e7.tar.bz2 |
SF bug 433228: repr(list) woes when len(list) big.
Gave Python linear-time repr() implementations for dicts, lists, strings.
This means, e.g., that repr(range(50000)) is no longer 50x slower than
pprint.pprint() in 2.2 <wink>.
I don't consider this a bugfix candidate, as it's a performance boost.
Added _PyString_Join() to the internal string API. If we want that in the
public API, fine, but then it requires runtime error checks instead of
asserts.
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/dictobject.c | 98 | ||||
-rw-r--r-- | Objects/listobject.c | 68 | ||||
-rw-r--r-- | Objects/stringobject.c | 17 | ||||
-rw-r--r-- | Objects/tupleobject.c | 62 |
4 files changed, 189 insertions, 56 deletions
diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 21cc6c6..42bfd40 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -809,42 +809,80 @@ dict_print(register dictobject *mp, register FILE *fp, register int flags) static PyObject * dict_repr(dictobject *mp) { - auto PyObject *v; - PyObject *sepa, *colon; - register int i; - register int any; + int i, pos; + PyObject *s, *temp, *colon = NULL; + PyObject *pieces = NULL, *result = NULL; + PyObject *key, *value; - i = Py_ReprEnter((PyObject*)mp); + i = Py_ReprEnter((PyObject *)mp); if (i != 0) { - if (i > 0) - return PyString_FromString("{...}"); - return NULL; + return i > 0 ? PyString_FromString("{...}") : NULL; } - v = PyString_FromString("{"); - sepa = PyString_FromString(", "); - colon = PyString_FromString(": "); - any = 0; - for (i = 0; i <= mp->ma_mask && v; i++) { - dictentry *ep = mp->ma_table + i; - PyObject *pvalue = ep->me_value; - if (pvalue != NULL) { - /* Prevent PyObject_Repr from deleting value during - key format */ - Py_INCREF(pvalue); - if (any++) - PyString_Concat(&v, sepa); - PyString_ConcatAndDel(&v, PyObject_Repr(ep->me_key)); - PyString_Concat(&v, colon); - PyString_ConcatAndDel(&v, PyObject_Repr(pvalue)); - Py_DECREF(pvalue); - } + if (mp->ma_used == 0) { + result = PyString_FromString("{}"); + goto Done; } - PyString_ConcatAndDel(&v, PyString_FromString("}")); - Py_ReprLeave((PyObject*)mp); - Py_XDECREF(sepa); + + pieces = PyList_New(0); + if (pieces == NULL) + goto Done; + + colon = PyString_FromString(": "); + if (colon == NULL) + goto Done; + + /* Do repr() on each key+value pair, and insert ": " between them. + Note that repr may mutate the dict. */ + pos = 0; + while (PyDict_Next((PyObject *)mp, &pos, &key, &value)) { + int status; + /* Prevent repr from deleting value during key format. */ + Py_INCREF(value); + s = PyObject_Repr(key); + PyString_Concat(&s, colon); + PyString_ConcatAndDel(&s, PyObject_Repr(value)); + Py_DECREF(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 = PyString_FromString("{"); + if (s == NULL) + goto Done; + temp = PyList_GET_ITEM(pieces, 0); + PyString_ConcatAndDel(&s, temp); + PyList_SET_ITEM(pieces, 0, s); + if (s == NULL) + goto Done; + + s = PyString_FromString("}"); + if (s == NULL) + goto Done; + temp = PyList_GET_ITEM(pieces, PyList_GET_SIZE(pieces) - 1); + PyString_ConcatAndDel(&temp, s); + PyList_SET_ITEM(pieces, PyList_GET_SIZE(pieces) - 1, temp); + if (temp == NULL) + goto Done; + + /* Paste them all together with ", " between. */ + s = PyString_FromString(", "); + if (s == NULL) + goto Done; + result = _PyString_Join(s, pieces); + Py_DECREF(s); + +Done: + Py_XDECREF(pieces); Py_XDECREF(colon); - return v; + Py_ReprLeave((PyObject *)mp); + return result; } static int diff --git a/Objects/listobject.c b/Objects/listobject.c index e595c85..6fb3145 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -246,26 +246,68 @@ list_print(PyListObject *op, FILE *fp, int flags) static PyObject * list_repr(PyListObject *v) { - PyObject *s, *comma; int i; + PyObject *s, *temp; + PyObject *pieces = NULL, *result = NULL; i = Py_ReprEnter((PyObject*)v); if (i != 0) { - if (i > 0) - return PyString_FromString("[...]"); - return NULL; + return i > 0 ? PyString_FromString("[...]") : NULL; } - s = PyString_FromString("["); - comma = PyString_FromString(", "); - for (i = 0; i < v->ob_size && s != NULL; i++) { - if (i > 0) - PyString_Concat(&s, comma); - PyString_ConcatAndDel(&s, PyObject_Repr(v->ob_item[i])); + + if (v->ob_size == 0) { + result = PyString_FromString("[]"); + goto Done; } - Py_XDECREF(comma); - PyString_ConcatAndDel(&s, PyString_FromString("]")); + + pieces = PyList_New(0); + if (pieces == NULL) + goto Done; + + /* Do repr() on each element. Note that this may mutate the list, + so must refetch the list size on each iteration. */ + for (i = 0; i < v->ob_size; ++i) { + int status; + s = PyObject_Repr(v->ob_item[i]); + 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 = PyString_FromString("["); + if (s == NULL) + goto Done; + temp = PyList_GET_ITEM(pieces, 0); + PyString_ConcatAndDel(&s, temp); + PyList_SET_ITEM(pieces, 0, s); + if (s == NULL) + goto Done; + + s = PyString_FromString("]"); + if (s == NULL) + goto Done; + temp = PyList_GET_ITEM(pieces, PyList_GET_SIZE(pieces) - 1); + PyString_ConcatAndDel(&temp, s); + PyList_SET_ITEM(pieces, PyList_GET_SIZE(pieces) - 1, temp); + if (temp == NULL) + goto Done; + + /* Paste them all together with ", " between. */ + s = PyString_FromString(", "); + if (s == NULL) + goto Done; + result = _PyString_Join(s, pieces); + Py_DECREF(s); + +Done: + Py_XDECREF(pieces); Py_ReprLeave((PyObject *)v); - return s; + return result; } static int diff --git a/Objects/stringobject.c b/Objects/stringobject.c index bcf5147..24443d8 100644 --- a/Objects/stringobject.c +++ b/Objects/stringobject.c @@ -1031,6 +1031,23 @@ string_join(PyStringObject *self, PyObject *args) return res; } +PyObject *_PyString_Join(PyObject *sep, PyObject *x) +{ + PyObject* args; + PyObject* result = NULL; + + assert(sep != NULL && PyString_Check(sep)); + assert(x != NULL); + args = PyTuple_New(1); + if (args != NULL) { + Py_INCREF(x); + PyTuple_SET_ITEM(args, 0, x); + result = string_join((PyStringObject *)sep, args); + Py_DECREF(args); + } + return result; +} + static long string_find_internal(PyStringObject *self, PyObject *args, int dir) { diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index 17ec1a0..538cc70 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -184,20 +184,56 @@ tupleprint(PyTupleObject *op, FILE *fp, int flags) static PyObject * tuplerepr(PyTupleObject *v) { - PyObject *s, *comma; - int i; + int i, n; + PyObject *s, *temp; + PyObject *pieces, *result = NULL; + + n = v->ob_size; + if (n == 0) + return PyString_FromString("()"); + + pieces = PyTuple_New(n); + if (pieces == NULL) + return NULL; + + /* Do repr() on each element. */ + for (i = 0; i < n; ++i) { + s = PyObject_Repr(v->ob_item[i]); + if (s == NULL) + goto Done; + PyTuple_SET_ITEM(pieces, i, s); + } + + /* Add "()" decorations to the first and last items. */ + assert(n > 0); s = PyString_FromString("("); - comma = PyString_FromString(", "); - for (i = 0; i < v->ob_size && s != NULL; i++) { - if (i > 0) - PyString_Concat(&s, comma); - PyString_ConcatAndDel(&s, PyObject_Repr(v->ob_item[i])); - } - Py_DECREF(comma); - if (v->ob_size == 1) - PyString_ConcatAndDel(&s, PyString_FromString(",")); - PyString_ConcatAndDel(&s, PyString_FromString(")")); - return s; + if (s == NULL) + goto Done; + temp = PyTuple_GET_ITEM(pieces, 0); + PyString_ConcatAndDel(&s, temp); + PyTuple_SET_ITEM(pieces, 0, s); + if (s == NULL) + goto Done; + + s = PyString_FromString(n == 1 ? ",)" : ")"); + if (s == NULL) + goto Done; + temp = PyTuple_GET_ITEM(pieces, n-1); + PyString_ConcatAndDel(&temp, s); + PyTuple_SET_ITEM(pieces, n-1, temp); + if (temp == NULL) + goto Done; + + /* Paste them all together with ", " between. */ + s = PyString_FromString(", "); + if (s == NULL) + goto Done; + result = _PyString_Join(s, pieces); + Py_DECREF(s); + +Done: + Py_DECREF(pieces); + return result; } static long |