diff options
author | Armin Rigo <arigo@tunes.org> | 2004-07-30 11:38:22 (GMT) |
---|---|---|
committer | Armin Rigo <arigo@tunes.org> | 2004-07-30 11:38:22 (GMT) |
commit | 1dd04a02e03e1765d9f2096d979de92927337dcb (patch) | |
tree | 5bbc0038acb57ed18f360cd01b482c1c3ac685f6 | |
parent | a37bbf2e5bf9d0854a774cdd1a972d0b7cc9e733 (diff) | |
download | cpython-1dd04a02e03e1765d9f2096d979de92927337dcb.zip cpython-1dd04a02e03e1765d9f2096d979de92927337dcb.tar.gz cpython-1dd04a02e03e1765d9f2096d979de92927337dcb.tar.bz2 |
This is a reorganization of list_ass_slice(). It should probably be reviewed,
though I tried to be very careful. This is a slight simplification, and it
adds a new feature: a small stack-allocated "recycled" array for the cases
when we don't remove too many items.
It allows PyList_SetSlice() to never fail if:
* you are sure that the object is a list; and
* you either do not remove more than 8 items, or clear the list.
This makes a number of other places in the source code correct again -- there
are some places that delete a single item without checking for MemoryErrors
raised by PyList_SetSlice(), or that clear the whole list, and sometimes the
context doesn't allow an error to be propagated.
-rw-r--r-- | Objects/listobject.c | 42 |
1 files changed, 20 insertions, 22 deletions
diff --git a/Objects/listobject.c b/Objects/listobject.c index bd5b95a..2adc4f4 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -517,6 +517,7 @@ list_ass_slice(PyListObject *a, int ilow, int ihigh, PyObject *v) we temporarily copy the items that are deleted from the list. :-( */ PyObject **recycle, **p; + PyObject *recycled[8]; PyObject **item; PyObject **vitem = NULL; PyObject *v_as_SF = NULL; /* PySequence_Fast(v) */ @@ -559,8 +560,10 @@ list_ass_slice(PyListObject *a, int ilow, int ihigh, PyObject *v) return list_clear(a); } item = a->ob_item; - if (ihigh > ilow) { - p = recycle = PyMem_NEW(PyObject *, (ihigh-ilow)); + /* recycle the ihigh-ilow items that we are about to remove */ + s = (ihigh - ilow)*sizeof(PyObject *); + if (s > sizeof(recycled)) { + recycle = (PyObject **)PyMem_MALLOC(s); if (recycle == NULL) { PyErr_NoMemory(); Py_XDECREF(v_as_SF); @@ -568,41 +571,36 @@ list_ass_slice(PyListObject *a, int ilow, int ihigh, PyObject *v) } } else - p = recycle = NULL; - if (d <= 0) { /* Delete -d items; recycle ihigh-ilow items */ - memcpy(p, &item[ilow], (ihigh - ilow)*sizeof(PyObject *)); - p += ihigh - ilow; - if (d < 0) { - memmove(&item[ihigh+d], &item[ihigh], - (a->ob_size - ihigh)*sizeof(PyObject *)); - list_resize(a, a->ob_size + d); - item = a->ob_item; - } + recycle = recycled; + p = recycle + (ihigh - ilow); + memcpy(recycle, &item[ilow], s); + if (d < 0) { /* Delete -d items */ + memmove(&item[ihigh+d], &item[ihigh], + (a->ob_size - ihigh)*sizeof(PyObject *)); + list_resize(a, a->ob_size + d); + item = a->ob_item; } - else { /* Insert d items; recycle ihigh-ilow items */ + else if (d > 0) { /* Insert d items */ s = a->ob_size; if (list_resize(a, s+d) == -1) { - if (recycle != NULL) - PyMem_DEL(recycle); + if (recycle != recycled) + PyMem_FREE(recycle); Py_XDECREF(v_as_SF); return -1; } item = a->ob_item; memmove(&item[ihigh+d], &item[ihigh], (s - ihigh)*sizeof(PyObject *)); - memcpy(p, &item[ilow], (ihigh - ilow)*sizeof(PyObject *)); - p += ihigh - ilow; } for (k = 0; k < n; k++, ilow++) { PyObject *w = vitem[k]; Py_XINCREF(w); item[ilow] = w; } - if (recycle) { - while (--p >= recycle) - Py_XDECREF(*p); - PyMem_DEL(recycle); - } + while (--p >= recycle) + Py_XDECREF(*p); + if (recycle != recycled) + PyMem_FREE(recycle); Py_XDECREF(v_as_SF); return 0; #undef b |