[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 */