mirror of
https://github.com/python/cpython.git
synced 2025-08-03 08:34:29 +00:00
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.
This commit is contained in:
parent
a37bbf2e5b
commit
1dd04a02e0
1 changed files with 20 additions and 22 deletions
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue