[Python-checkins] python/dist/src/Objects iterobject.c,1.10,1.11
gvanrossum@users.sourceforge.net
gvanrossum@users.sourceforge.net
Tue, 16 Jul 2002 13:24:49 -0700
Update of /cvsroot/python/python/dist/src/Objects
In directory usw-pr-cvs1:/tmp/cvs-serv1699
Modified Files:
iterobject.c
Log Message:
Make StopIteration a sink state. This is done by clearing out the
object references (it_seq for seqiterobject, it_callable and
it_sentinel for calliterobject) when the end of the list is reached.
Also remove the next() methods -- 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).
Index: iterobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/iterobject.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -C2 -d -r1.10 -r1.11
*** iterobject.c 31 May 2002 21:37:01 -0000 1.10
--- iterobject.c 16 Jul 2002 20:24:46 -0000 1.11
***************
*** 6,10 ****
PyObject_HEAD
long it_index;
! PyObject *it_seq;
} seqiterobject;
--- 6,10 ----
PyObject_HEAD
long it_index;
! PyObject *it_seq; /* Set to NULL when iterator is exhausted */
} seqiterobject;
***************
*** 27,35 ****
return (PyObject *)it;
}
static void
iter_dealloc(seqiterobject *it)
{
_PyObject_GC_UNTRACK(it);
! Py_DECREF(it->it_seq);
PyObject_GC_Del(it);
}
--- 27,36 ----
return (PyObject *)it;
}
+
static void
iter_dealloc(seqiterobject *it)
{
_PyObject_GC_UNTRACK(it);
! Py_XDECREF(it->it_seq);
PyObject_GC_Del(it);
}
***************
*** 38,56 ****
iter_traverse(seqiterobject *it, visitproc visit, void *arg)
{
return visit(it->it_seq, arg);
}
static PyObject *
- iter_next(seqiterobject *it)
- {
- PyObject *seq = it->it_seq;
- PyObject *result = PySequence_GetItem(seq, it->it_index++);
-
- if (result == NULL && PyErr_ExceptionMatches(PyExc_IndexError))
- PyErr_SetObject(PyExc_StopIteration, Py_None);
- return result;
- }
-
- static PyObject *
iter_getiter(PyObject *it)
{
--- 39,48 ----
iter_traverse(seqiterobject *it, visitproc visit, void *arg)
{
+ if (it->it_seq == NULL)
+ return 0;
return visit(it->it_seq, arg);
}
static PyObject *
iter_getiter(PyObject *it)
{
***************
*** 68,71 ****
--- 60,65 ----
it = (seqiterobject *)iterator;
seq = it->it_seq;
+ if (seq == NULL)
+ return NULL;
if (PyTuple_CheckExact(seq)) {
***************
*** 77,105 ****
return item;
}
return NULL;
}
else {
! PyObject *result = PySequence_ITEM(seq, it->it_index);
! it->it_index++;
if (result != NULL) {
return result;
}
if (PyErr_ExceptionMatches(PyExc_IndexError) ||
! PyErr_ExceptionMatches(PyExc_StopIteration)) {
PyErr_Clear();
! return NULL;
! }
! else {
! return NULL;
}
}
}
- static PyMethodDef iter_methods[] = {
- {"next", (PyCFunction)iter_next, METH_NOARGS,
- "it.next() -- get the next value, or raise StopIteration"},
- {NULL, NULL} /* sentinel */
- };
-
PyTypeObject PySeqIter_Type = {
PyObject_HEAD_INIT(&PyType_Type)
--- 71,95 ----
return item;
}
+ Py_DECREF(seq);
+ it->it_seq = NULL;
return NULL;
}
else {
! PyObject *result = PySequence_GetItem(seq, it->it_index);
if (result != NULL) {
+ it->it_index++;
return result;
}
if (PyErr_ExceptionMatches(PyExc_IndexError) ||
! PyErr_ExceptionMatches(PyExc_StopIteration))
! {
PyErr_Clear();
! Py_DECREF(seq);
! it->it_seq = NULL;
}
+ return NULL;
}
}
PyTypeObject PySeqIter_Type = {
PyObject_HEAD_INIT(&PyType_Type)
***************
*** 132,136 ****
(getiterfunc)iter_getiter, /* tp_iter */
(iternextfunc)iter_iternext, /* tp_iternext */
! iter_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
--- 122,126 ----
(getiterfunc)iter_getiter, /* tp_iter */
(iternextfunc)iter_iternext, /* tp_iternext */
! 0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
***************
*** 145,150 ****
typedef struct {
PyObject_HEAD
! PyObject *it_callable;
! PyObject *it_sentinel;
} calliterobject;
--- 135,140 ----
typedef struct {
PyObject_HEAD
! PyObject *it_callable; /* Set to NULL when iterator is exhausted */
! PyObject *it_sentinel; /* Set to NULL when iterator is exhausted */
} calliterobject;
***************
*** 167,172 ****
{
_PyObject_GC_UNTRACK(it);
! Py_DECREF(it->it_callable);
! Py_DECREF(it->it_sentinel);
PyObject_GC_Del(it);
}
--- 157,162 ----
{
_PyObject_GC_UNTRACK(it);
! Py_XDECREF(it->it_callable);
! Py_XDECREF(it->it_sentinel);
PyObject_GC_Del(it);
}
***************
*** 176,182 ****
{
int err;
! if ((err = visit(it->it_callable, arg)))
return err;
! if ((err = visit(it->it_sentinel, arg)))
return err;
return 0;
--- 166,172 ----
{
int err;
! if (it->it_callable != NULL && (err = visit(it->it_callable, arg)))
return err;
! if (it->it_sentinel != NULL && (err = visit(it->it_sentinel, arg)))
return err;
return 0;
***************
*** 184,220 ****
static PyObject *
- calliter_next(calliterobject *it, PyObject *args)
- {
- PyObject *result = PyObject_CallObject(it->it_callable, NULL);
- if (result != NULL) {
- if (PyObject_RichCompareBool(result, it->it_sentinel, Py_EQ)) {
- PyErr_SetObject(PyExc_StopIteration, Py_None);
- Py_DECREF(result);
- result = NULL;
- }
- }
- return result;
- }
-
- static PyMethodDef calliter_methods[] = {
- {"next", (PyCFunction)calliter_next, METH_VARARGS,
- "it.next() -- get the next value, or raise StopIteration"},
- {NULL, NULL} /* sentinel */
- };
-
- static PyObject *
calliter_iternext(calliterobject *it)
{
! PyObject *result = PyObject_CallObject(it->it_callable, NULL);
! if (result != NULL) {
! if (PyObject_RichCompareBool(result, it->it_sentinel, Py_EQ)) {
Py_DECREF(result);
! result = NULL;
}
}
! else if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
! PyErr_Clear();
! }
! return result;
}
--- 174,205 ----
static PyObject *
calliter_iternext(calliterobject *it)
{
! if (it->it_callable != NULL) {
! PyObject *result = PyObject_CallObject(it->it_callable, NULL);
! if (result != NULL) {
! int ok;
! ok = PyObject_RichCompareBool(result,
! it->it_sentinel,
! Py_EQ);
! if (ok == 0)
! return result; /* Common case, fast path */
Py_DECREF(result);
! if (ok > 0) {
! Py_DECREF(it->it_callable);
! it->it_callable = NULL;
! Py_DECREF(it->it_sentinel);
! it->it_sentinel = NULL;
! }
! }
! else if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
! PyErr_Clear();
! Py_DECREF(it->it_callable);
! it->it_callable = NULL;
! Py_DECREF(it->it_sentinel);
! it->it_sentinel = NULL;
}
}
! return NULL;
}
***************
*** 249,253 ****
(getiterfunc)iter_getiter, /* tp_iter */
(iternextfunc)calliter_iternext, /* tp_iternext */
! calliter_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
--- 234,238 ----
(getiterfunc)iter_getiter, /* tp_iter */
(iternextfunc)calliter_iternext, /* tp_iternext */
! 0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */