summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Objects/listobject.c76
1 files changed, 25 insertions, 51 deletions
diff --git a/Objects/listobject.c b/Objects/listobject.c
index f34ca70..890c279 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -647,56 +647,6 @@ listappend(PyListObject *self, PyObject *v)
return ins(self, (int) self->ob_size, v);
}
-static int
-listextend_internal(PyListObject *self, PyObject *b)
-{
- int selflen = PyList_GET_SIZE(self);
- int blen;
- register int i;
- PyObject **src, **dest;
-
- blen = PyObject_Size(b);
- if (blen == 0) {
- /* short circuit when b is empty */
- Py_DECREF(b);
- return 0;
- }
-
- if (self == (PyListObject*)b) {
- /* as in list_ass_slice() we must special case the
- * situation: a.extend(a)
- *
- * XXX: I think this way ought to be faster than using
- * list_slice() the way list_ass_slice() does.
- */
- Py_DECREF(b);
- b = PyList_New(selflen);
- if (!b)
- return -1;
- for (i = 0; i < selflen; i++) {
- PyObject *o = PyList_GET_ITEM(self, i);
- Py_INCREF(o);
- PyList_SET_ITEM(b, i, o);
- }
- }
-
- if (list_resize(self, selflen + blen) == -1) {
- Py_DECREF(b);
- return -1;
- }
-
- /* populate the end of self with b's items */
- src = PySequence_Fast_ITEMS(b);
- dest = self->ob_item + selflen;
- for (i = 0; i < blen; i++) {
- PyObject *o = src[i];
- Py_INCREF(o);
- dest[i] = o;
- }
- Py_DECREF(b);
- return 0;
-}
-
static PyObject *
listextend(PyListObject *self, PyObject *b)
{
@@ -712,11 +662,35 @@ listextend(PyListObject *self, PyObject *b)
2) extending self to self requires making a copy first
*/
if (PyList_CheckExact(b) || PyTuple_CheckExact(b) || (PyObject *)self == b) {
+ PyObject **src, **dest;
b = PySequence_Fast(b, "argument must be iterable");
if (!b)
return NULL;
- if (listextend_internal(self, b) < 0)
+ n = PySequence_Fast_GET_SIZE(b);
+ if (n == 0) {
+ /* short circuit when b is empty */
+ Py_DECREF(b);
+ Py_RETURN_NONE;
+ }
+ m = self->ob_size;
+ if (list_resize(self, m + n) == -1) {
+ Py_DECREF(b);
return NULL;
+ }
+ /* note that we may still have self == b here for the
+ * situation a.extend(a), but the following code works
+ * in that case too. Just make sure to resize self
+ * before calling PySequence_Fast_ITEMS.
+ */
+ /* populate the end of self with b's items */
+ src = PySequence_Fast_ITEMS(b);
+ dest = self->ob_item + m;
+ for (i = 0; i < n; i++) {
+ PyObject *o = src[i];
+ Py_INCREF(o);
+ dest[i] = o;
+ }
+ Py_DECREF(b);
Py_RETURN_NONE;
}