Commit 86103ae5 authored by Guido van Rossum's avatar Guido van Rossum

Make StopIteration a sink state. This is done by clearing out the

it_seq field when the end of the list is reached.

Also remove the next() method -- one is supplied automatically by
PyType_Ready() because the tp_iternext slot is set.  That's a good
thing, because the implementation given here was buggy (it never
raised StopIteration).
parent 9534e140
/* List object implementation */ /* List object implementation */
#include "Python.h" #include "Python.h"
...@@ -2016,7 +2015,7 @@ static PyTypeObject immutable_list_type = { ...@@ -2016,7 +2015,7 @@ static PyTypeObject immutable_list_type = {
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD
long it_index; long it_index;
PyListObject *it_seq; PyListObject *it_seq; /* Set to NULL when iterator is exhausted */
} listiterobject; } listiterobject;
PyTypeObject PyListIter_Type; PyTypeObject PyListIter_Type;
...@@ -2044,13 +2043,15 @@ static void ...@@ -2044,13 +2043,15 @@ static void
listiter_dealloc(listiterobject *it) listiter_dealloc(listiterobject *it)
{ {
_PyObject_GC_UNTRACK(it); _PyObject_GC_UNTRACK(it);
Py_DECREF(it->it_seq); Py_XDECREF(it->it_seq);
PyObject_GC_Del(it); PyObject_GC_Del(it);
} }
static int static int
listiter_traverse(listiterobject *it, visitproc visit, void *arg) listiter_traverse(listiterobject *it, visitproc visit, void *arg)
{ {
if (it->it_seq == NULL)
return 0;
return visit((PyObject *)it->it_seq, arg); return visit((PyObject *)it->it_seq, arg);
} }
...@@ -2070,6 +2071,8 @@ listiter_next(listiterobject *it) ...@@ -2070,6 +2071,8 @@ listiter_next(listiterobject *it)
assert(it != NULL); assert(it != NULL);
seq = it->it_seq; seq = it->it_seq;
if (seq == NULL)
return NULL;
assert(PyList_Check(seq)); assert(PyList_Check(seq));
if (it->it_index < PyList_GET_SIZE(seq)) { if (it->it_index < PyList_GET_SIZE(seq)) {
...@@ -2078,15 +2081,12 @@ listiter_next(listiterobject *it) ...@@ -2078,15 +2081,12 @@ listiter_next(listiterobject *it)
Py_INCREF(item); Py_INCREF(item);
return item; return item;
} }
Py_DECREF(seq);
it->it_seq = NULL;
return NULL; return NULL;
} }
static PyMethodDef listiter_methods[] = {
{"next", (PyCFunction)listiter_next, METH_NOARGS,
"it.next() -- get the next value, or raise StopIteration"},
{NULL, NULL} /* sentinel */
};
PyTypeObject PyListIter_Type = { PyTypeObject PyListIter_Type = {
PyObject_HEAD_INIT(&PyType_Type) PyObject_HEAD_INIT(&PyType_Type)
0, /* ob_size */ 0, /* ob_size */
...@@ -2117,7 +2117,7 @@ PyTypeObject PyListIter_Type = { ...@@ -2117,7 +2117,7 @@ PyTypeObject PyListIter_Type = {
0, /* tp_weaklistoffset */ 0, /* tp_weaklistoffset */
(getiterfunc)listiter_getiter, /* tp_iter */ (getiterfunc)listiter_getiter, /* tp_iter */
(iternextfunc)listiter_next, /* tp_iternext */ (iternextfunc)listiter_next, /* tp_iternext */
listiter_methods, /* tp_methods */ 0, /* tp_methods */
0, /* tp_members */ 0, /* tp_members */
0, /* tp_getset */ 0, /* tp_getset */
0, /* tp_base */ 0, /* tp_base */
...@@ -2125,4 +2125,3 @@ PyTypeObject PyListIter_Type = { ...@@ -2125,4 +2125,3 @@ PyTypeObject PyListIter_Type = {
0, /* tp_descr_get */ 0, /* tp_descr_get */
0, /* tp_descr_set */ 0, /* tp_descr_set */
}; };
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment