From 194e43e9533b0441b4f5d680f1d0c77e20297a34 Mon Sep 17 00:00:00 2001 From: Jeremy Hylton Date: Mon, 10 Jul 2000 21:30:28 +0000 Subject: two changes to string_join: implementation -- use PySequence_Fast interface to iterate over elements interface -- if instance object reports wrong length, ignore it; previous version raised an IndexError if reported length was too high --- Objects/stringobject.c | 124 +++++++++++++++++-------------------------------- 1 file changed, 42 insertions(+), 82 deletions(-) diff --git a/Objects/stringobject.c b/Objects/stringobject.c index 9677d4b..fd0a570 100644 --- a/Objects/stringobject.c +++ b/Objects/stringobject.c @@ -744,106 +744,66 @@ string_join(PyStringObject *self, PyObject *args) int seqlen = 0; int sz = 100; int i, slen; - PyObject *seq; + PyObject *orig, *seq, *item; - if (!PyArg_ParseTuple(args, "O:join", &seq)) + if (!PyArg_ParseTuple(args, "O:join", &orig)) return NULL; - seqlen = PySequence_Length(seq); - if (seqlen < 0 && PyErr_Occurred()) + seq = PySequence_Fast(orig, ""); + if (seq == NULL) { + if (PyErr_ExceptionMatches(PyExc_TypeError)) + PyErr_Format(PyExc_TypeError, + "sequence expected, %.80s found", + orig->ob_type->tp_name); return NULL; + } + seqlen = PySequence_Length(seq); if (seqlen == 1) { - /* Optimization if there's only one item */ - PyObject *item = PySequence_GetItem(seq, 0); - if (item == NULL) - return NULL; - if (!PyString_Check(item) && - !PyUnicode_Check(item)) { - PyErr_SetString(PyExc_TypeError, - "first argument must be sequence of strings"); - Py_DECREF(item); - return NULL; - } + item = PySequence_Fast_GET_ITEM(seq, 0); + Py_INCREF(item); return item; } + if (!(res = PyString_FromStringAndSize((char*)NULL, sz))) return NULL; p = PyString_AsString(res); - /* optimize for lists. all others (tuples and arbitrary sequences) - * just use the abstract interface. - */ - if (PyList_Check(seq)) { - for (i = 0; i < seqlen; i++) { - PyObject *item = PyList_GET_ITEM(seq, i); - if (!PyString_Check(item)){ - if (PyUnicode_Check(item)) { - Py_DECREF(res); - return PyUnicode_Join( - (PyObject *)self, - seq); - } - PyErr_Format(PyExc_TypeError, - "sequence item %i not a string", - i); - goto finally; - } - slen = PyString_GET_SIZE(item); - while (reslen + slen + seplen >= sz) { - if (_PyString_Resize(&res, sz*2)) - goto finally; - sz *= 2; - p = PyString_AsString(res) + reslen; - } - if (i > 0) { - memcpy(p, sep, seplen); - p += seplen; - reslen += seplen; + for (i = 0; i < seqlen; i++) { + item = PySequence_Fast_GET_ITEM(seq, i); + if (!PyString_Check(item)){ + if (PyUnicode_Check(item)) { + Py_DECREF(res); + Py_DECREF(item); + return PyUnicode_Join((PyObject *)self, + seq); } - memcpy(p, PyString_AS_STRING(item), slen); - p += slen; - reslen += slen; + PyErr_Format(PyExc_TypeError, + "sequence item %i: expected string, %.80s found", + i, item->ob_type->tp_name); + Py_DECREF(item); + Py_DECREF(seq); + goto finally; } - } - else { - for (i = 0; i < seqlen; i++) { - PyObject *item = PySequence_GetItem(seq, i); - if (!item) - goto finally; - if (!PyString_Check(item)){ - if (PyUnicode_Check(item)) { - Py_DECREF(res); - Py_DECREF(item); - return PyUnicode_Join( - (PyObject *)self, - seq); - } + slen = PyString_GET_SIZE(item); + while (reslen + slen + seplen >= sz) { + if (_PyString_Resize(&res, sz*2)) { Py_DECREF(item); - PyErr_Format(PyExc_TypeError, - "sequence item %i not a string", - i); + Py_DECREF(seq); goto finally; } - slen = PyString_GET_SIZE(item); - while (reslen + slen + seplen >= sz) { - if (_PyString_Resize(&res, sz*2)) { - Py_DECREF(item); - goto finally; - } - sz *= 2; - p = PyString_AsString(res) + reslen; - } - if (i > 0) { - memcpy(p, sep, seplen); - p += seplen; - reslen += seplen; - } - memcpy(p, PyString_AS_STRING(item), slen); - Py_DECREF(item); - p += slen; - reslen += slen; + sz *= 2; + p = PyString_AsString(res) + reslen; + } + if (i > 0) { + memcpy(p, sep, seplen); + p += seplen; + reslen += seplen; } + memcpy(p, PyString_AS_STRING(item), slen); + Py_DECREF(item); + p += slen; + reslen += slen; } if (_PyString_Resize(&res, reslen)) goto finally; -- cgit v0.12