Created
March 28, 2011 14:26
-
-
Save oyvindio/890555 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* a[ilow:ihigh] = v if v != NULL. | |
* del a[ilow:ihigh] if v == NULL. | |
* | |
* Special speed gimmick: when v is NULL and ihigh - ilow <= 8, it's | |
* guaranteed the call cannot fail. | |
*/ | |
static int | |
list_ass_slice(PyListObject *a, Py_ssize_t ilow, Py_ssize_t ihigh, PyObject *v) | |
{ | |
/* Because [X]DECREF can recursively invoke list operations on | |
this list, we must postpone all [X]DECREF activity until | |
after the list is back in its canonical shape. Therefore | |
we must allocate an additional array, 'recycle', into which | |
we temporarily copy the items that are deleted from the | |
list. :-( */ | |
PyObject *recycle_on_stack[8]; | |
PyObject **recycle = recycle_on_stack; /* will allocate more if needed */ | |
PyObject **item; | |
PyObject **vitem = NULL; | |
PyObject *v_as_SF = NULL; /* PySequence_Fast(v) */ | |
Py_ssize_t n; /* # of elements in replacement list */ | |
Py_ssize_t norig; /* # of elements in list getting replaced */ | |
Py_ssize_t d; /* Change in size */ | |
Py_ssize_t k; | |
size_t s; | |
int result = -1; /* guilty until proved innocent */ | |
#define b ((PyListObject *)v) | |
if (v == NULL) | |
n = 0; | |
else { | |
if (a == b) { | |
/* Special case "a[i:j] = a" -- copy b first */ | |
v = list_slice(b, 0, Py_SIZE(b)); | |
if (v == NULL) | |
return result; | |
result = list_ass_slice(a, ilow, ihigh, v); | |
Py_DECREF(v); | |
return result; | |
} | |
v_as_SF = PySequence_Fast(v, "can only assign an iterable"); | |
if(v_as_SF == NULL) | |
goto Error; | |
n = PySequence_Fast_GET_SIZE(v_as_SF); | |
vitem = PySequence_Fast_ITEMS(v_as_SF); | |
} | |
if (ilow < 0) | |
ilow = 0; | |
else if (ilow > Py_SIZE(a)) | |
ilow = Py_SIZE(a); | |
if (ihigh < ilow) | |
ihigh = ilow; | |
else if (ihigh > Py_SIZE(a)) | |
ihigh = Py_SIZE(a); | |
norig = ihigh - ilow; | |
assert(norig >= 0); | |
d = n - norig; | |
if (Py_SIZE(a) + d == 0) { | |
Py_XDECREF(v_as_SF); | |
return list_clear(a); | |
} | |
item = a->ob_item; | |
/* recycle the items that we are about to remove */ | |
s = norig * sizeof(PyObject *); | |
if (s > sizeof(recycle_on_stack)) { | |
recycle = (PyObject **)PyMem_MALLOC(s); | |
if (recycle == NULL) { | |
PyErr_NoMemory(); | |
goto Error; | |
} | |
} | |
memcpy(recycle, &item[ilow], s); | |
if (d < 0) { /* Delete -d items */ | |
memmove(&item[ihigh+d], &item[ihigh], | |
(Py_SIZE(a) - ihigh)*sizeof(PyObject *)); | |
list_resize(a, Py_SIZE(a) + d); | |
item = a->ob_item; | |
} | |
else if (d > 0) { /* Insert d items */ | |
k = Py_SIZE(a); | |
if (list_resize(a, k+d) < 0) | |
goto Error; | |
item = a->ob_item; | |
memmove(&item[ihigh+d], &item[ihigh], | |
(k - ihigh)*sizeof(PyObject *)); | |
} | |
for (k = 0; k < n; k++, ilow++) { | |
PyObject *w = vitem[k]; | |
Py_XINCREF(w); | |
item[ilow] = w; | |
} | |
for (k = norig - 1; k >= 0; --k) | |
Py_XDECREF(recycle[k]); | |
result = 0; | |
Error: | |
if (recycle != recycle_on_stack) | |
PyMem_FREE(recycle); | |
Py_XDECREF(v_as_SF); | |
return result; | |
#undef b | |
} | |
int | |
PyList_SetSlice(PyObject *a, Py_ssize_t ilow, Py_ssize_t ihigh, PyObject *v) | |
{ | |
if (!PyList_Check(a)) { | |
PyErr_BadInternalCall(); | |
return -1; | |
} | |
return list_ass_slice((PyListObject *)a, ilow, ihigh, v); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment