summaryrefslogtreecommitdiffstats
path: root/Objects/listobject.c
diff options
context:
space:
mode:
Diffstat (limited to 'Objects/listobject.c')
-rw-r--r--Objects/listobject.c43
1 files changed, 30 insertions, 13 deletions
diff --git a/Objects/listobject.c b/Objects/listobject.c
index 3de07c9..c5a4287 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -2461,6 +2461,9 @@ list_subscript(PyListObject* self, PyObject* item)
if (slicelength <= 0) {
return PyList_New(0);
}
+ else if (step == 1) {
+ return list_slice(self, start, stop);
+ }
else {
result = PyList_New(slicelength);
if (!result) return NULL;
@@ -2504,10 +2507,15 @@ list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
return -1;
}
- /* treat L[slice(a,b)] = v _exactly_ like L[a:b] = v */
- if (step == 1 && ((PySliceObject*)item)->step == Py_None)
+ if (step == 1)
return list_ass_slice(self, start, stop, value);
+ /* Make sure s[5:2] = [..] inserts at the right place:
+ before 5, not before 2. */
+ if ((step < 0 && start < stop) ||
+ (step > 0 && start > stop))
+ stop = start;
+
if (value == NULL) {
/* delete slice */
PyObject **garbage;
@@ -2529,12 +2537,16 @@ list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
return -1;
}
- /* drawing pictures might help
- understand these for loops */
+ /* drawing pictures might help understand these for
+ loops. Basically, we memmove the parts of the
+ list that are *not* part of the slice: step-1
+ items for each item that is part of the slice,
+ and then tail end of the list that was not
+ covered by the slice */
for (cur = start, i = 0;
cur < stop;
cur += step, i++) {
- Py_ssize_t lim = step;
+ Py_ssize_t lim = step - 1;
garbage[i] = PyList_GET_ITEM(self, cur);
@@ -2546,11 +2558,12 @@ list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
self->ob_item + cur + 1,
lim * sizeof(PyObject *));
}
-
- for (cur = start + slicelength*step + 1;
- cur < Py_Size(self); cur++) {
- PyList_SET_ITEM(self, cur - slicelength,
- PyList_GET_ITEM(self, cur));
+ cur = start + slicelength*step;
+ if (cur < Py_Size(self)) {
+ memmove(self->ob_item + cur - slicelength,
+ self->ob_item + cur,
+ (Py_Size(self) - cur) *
+ sizeof(PyObject *));
}
Py_Size(self) -= slicelength;
@@ -2565,7 +2578,8 @@ list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
}
else {
/* assign slice */
- PyObject **garbage, *ins, *seq, **seqitems, **selfitems;
+ PyObject *ins, *seq;
+ PyObject **garbage, **seqitems, **selfitems;
Py_ssize_t cur, i;
/* protect against a[::-1] = a */
@@ -2575,14 +2589,17 @@ list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
}
else {
seq = PySequence_Fast(value,
- "must assign iterable to extended slice");
+ "must assign iterable "
+ "to extended slice");
}
if (!seq)
return -1;
if (PySequence_Fast_GET_SIZE(seq) != slicelength) {
PyErr_Format(PyExc_ValueError,
- "attempt to assign sequence of size %zd to extended slice of size %zd",
+ "attempt to assign sequence of "
+ "size %zd to extended slice of "
+ "size %zd",
PySequence_Fast_GET_SIZE(seq),
slicelength);
Py_DECREF(seq);