summaryrefslogtreecommitdiffstats
path: root/Objects/listobject.c
diff options
context:
space:
mode:
authorMichael W. Hudson <mwh@python.net>2002-06-11 10:55:12 (GMT)
committerMichael W. Hudson <mwh@python.net>2002-06-11 10:55:12 (GMT)
commit5efaf7eac8c1dbbf82a96dc5d9b87fddd5d17b58 (patch)
tree7358a0479ab98893ad5a5457ae0df328d0e60251 /Objects/listobject.c
parentf90ae20354ceb501f0ba0b6459df17f1a8005a47 (diff)
downloadcpython-5efaf7eac8c1dbbf82a96dc5d9b87fddd5d17b58.zip
cpython-5efaf7eac8c1dbbf82a96dc5d9b87fddd5d17b58.tar.gz
cpython-5efaf7eac8c1dbbf82a96dc5d9b87fddd5d17b58.tar.bz2
This is my nearly two year old patch
[ 400998 ] experimental support for extended slicing on lists somewhat spruced up and better tested than it was when I wrote it. Includes docs & tests. The whatsnew section needs expanding, and arrays should support extended slices -- later.
Diffstat (limited to 'Objects/listobject.c')
-rw-r--r--Objects/listobject.c188
1 files changed, 187 insertions, 1 deletions
diff --git a/Objects/listobject.c b/Objects/listobject.c
index bd391af..3ddf032 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -1684,6 +1684,192 @@ static char list_doc[] =
staticforward PyObject * list_iter(PyObject *seq);
+static PyObject*
+list_subscript(PyListObject* self, PyObject* item)
+{
+ if (PyInt_Check(item)) {
+ long i = PyInt_AS_LONG(item);
+ if (i < 0)
+ i += PyList_GET_SIZE(self);
+ return list_item(self, i);
+ }
+ else if (PyLong_Check(item)) {
+ long i = PyLong_AsLong(item);
+ if (i == -1 && PyErr_Occurred())
+ return NULL;
+ if (i < 0)
+ i += PyList_GET_SIZE(self);
+ return list_item(self, i);
+ }
+ else if (PySlice_Check(item)) {
+ int start, stop, step, slicelength, cur, i;
+ PyObject* result;
+ PyObject* it;
+
+ if (PySlice_GetIndicesEx((PySliceObject*)item, self->ob_size,
+ &start, &stop, &step, &slicelength) < 0) {
+ return NULL;
+ }
+
+ if (slicelength <= 0) {
+ return PyList_New(0);
+ }
+ else {
+ result = PyList_New(slicelength);
+ if (!result) return NULL;
+
+ for (cur = start, i = 0; i < slicelength;
+ cur += step, i++) {
+ it = PyList_GET_ITEM(self, cur);
+ Py_INCREF(it);
+ PyList_SET_ITEM(result, i, it);
+ }
+
+ return result;
+ }
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError,
+ "list indices must be integers");
+ return NULL;
+ }
+}
+
+static int
+list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
+{
+ if (PyInt_Check(item)) {
+ long i = PyInt_AS_LONG(item);
+ if (i < 0)
+ i += PyList_GET_SIZE(self);
+ return list_ass_item(self, i, value);
+ }
+ else if (PyLong_Check(item)) {
+ long i = PyLong_AsLong(item);
+ if (i == -1 && PyErr_Occurred())
+ return -1;
+ if (i < 0)
+ i += PyList_GET_SIZE(self);
+ return list_ass_item(self, i, value);
+ }
+ else if (PySlice_Check(item)) {
+ int start, stop, step, slicelength;
+
+ if (PySlice_GetIndicesEx((PySliceObject*)item, self->ob_size,
+ &start, &stop, &step, &slicelength) < 0) {
+ return -1;
+ }
+
+ if (value == NULL) {
+ /* delete slice */
+ PyObject **garbage, **item;
+ int cur, i, j;
+
+ if (slicelength <= 0)
+ return 0;
+
+ if (step < 0) {
+ stop = start + 1;
+ start = stop + step*(slicelength - 1) - 1;
+ step = -step;
+ }
+
+ garbage = (PyObject**)
+ PyMem_MALLOC(slicelength*sizeof(PyObject*));
+
+ /* drawing pictures might help
+ understand these for loops */
+ for (cur = start, i = 0; cur < stop; cur += step, i++) {
+ garbage[i] = PyList_GET_ITEM(self, cur);
+
+ for (j = 0; j < step; j++) {
+ PyList_SET_ITEM(self, cur + j - i,
+ PyList_GET_ITEM(self, cur + j + 1));
+ }
+ }
+ for (cur = start + slicelength*step + 1;
+ cur < self->ob_size; cur++) {
+ PyList_SET_ITEM(self, cur - slicelength,
+ PyList_GET_ITEM(self, cur));
+ }
+ self->ob_size -= slicelength;
+ item = self->ob_item;
+ NRESIZE(item, PyObject*, self->ob_size);
+ self->ob_item = item;
+
+ for (i = 0; i < slicelength; i++) {
+ Py_DECREF(garbage[i]);
+ }
+ PyMem_FREE(garbage);
+
+ return 0;
+ }
+ else {
+ /* assign slice */
+ PyObject **garbage, *ins;
+ int cur, i;
+
+ if (!PyList_Check(value)) {
+ PyErr_Format(PyExc_TypeError,
+ "must assign list (not \"%.200s\") to slice",
+ value->ob_type->tp_name);
+ return -1;
+ }
+
+ if (PyList_GET_SIZE(value) != slicelength) {
+ PyErr_Format(PyExc_ValueError,
+ "attempt to assign list of size %d to extended slice of size %d",
+ PyList_Size(value), slicelength);
+ return -1;
+ }
+
+ if (!slicelength)
+ return 0;
+
+ /* protect against a[::-1] = a */
+ if (self == (PyListObject*)value) {
+ value = list_slice((PyListObject*)value, 0,
+ PyList_GET_SIZE(value));
+ }
+ else {
+ Py_INCREF(value);
+ }
+
+ garbage = (PyObject**)
+ PyMem_MALLOC(slicelength*sizeof(PyObject*));
+
+ for (cur = start, i = 0; i < slicelength;
+ cur += step, i++) {
+ garbage[i] = PyList_GET_ITEM(self, cur);
+
+ ins = PyList_GET_ITEM(value, i);
+ Py_INCREF(ins);
+ PyList_SET_ITEM(self, cur, ins);
+ }
+
+ for (i = 0; i < slicelength; i++) {
+ Py_DECREF(garbage[i]);
+ }
+
+ PyMem_FREE(garbage);
+ Py_DECREF(value);
+
+ return 0;
+ }
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError,
+ "list indices must be integers");
+ return -1;
+ }
+}
+
+static PyMappingMethods list_as_mapping = {
+ (inquiry)list_length,
+ (binaryfunc)list_subscript,
+ (objobjargproc)list_ass_subscript
+};
+
PyTypeObject PyList_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0,
@@ -1698,7 +1884,7 @@ PyTypeObject PyList_Type = {
(reprfunc)list_repr, /* tp_repr */
0, /* tp_as_number */
&list_as_sequence, /* tp_as_sequence */
- 0, /* tp_as_mapping */
+ &list_as_mapping, /* tp_as_mapping */
list_nohash, /* tp_hash */
0, /* tp_call */
0, /* tp_str */