diff options
author | Guido van Rossum <guido@python.org> | 2002-07-16 20:30:22 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2002-07-16 20:30:22 (GMT) |
commit | 2147df748fa0a44beede227af9e595fe96fd7a14 (patch) | |
tree | c94b7dc11af97eebb6b2efbe0db4fe2e3f0910b5 | |
parent | 613bed3726af921be64900bd0cb8209193873411 (diff) | |
download | cpython-2147df748fa0a44beede227af9e595fe96fd7a14.zip cpython-2147df748fa0a44beede227af9e595fe96fd7a14.tar.gz cpython-2147df748fa0a44beede227af9e595fe96fd7a14.tar.bz2 |
Make StopIteration a sink state. This is done by clearing out the
di_dict field when the end of the list is reached. Also make the
error ("dictionary changed size during iteration") a sticky state.
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).
-rw-r--r-- | Objects/dictobject.c | 39 |
1 files changed, 11 insertions, 28 deletions
diff --git a/Objects/dictobject.c b/Objects/dictobject.c index d7bbef9..2619160 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -1916,7 +1916,7 @@ extern PyTypeObject PyDictIter_Type; /* Forward */ typedef struct { PyObject_HEAD - dictobject *di_dict; + dictobject *di_dict; /* Set to NULL when iterator is exhausted */ int di_used; int di_pos; binaryfunc di_select; @@ -1940,52 +1940,35 @@ dictiter_new(dictobject *dict, binaryfunc select) static void dictiter_dealloc(dictiterobject *di) { - Py_DECREF(di->di_dict); + Py_XDECREF(di->di_dict); PyObject_Del(di); } static PyObject * -dictiter_next(dictiterobject *di, PyObject *args) -{ - PyObject *key, *value; - - if (di->di_used != di->di_dict->ma_used) { - PyErr_SetString(PyExc_RuntimeError, - "dictionary changed size during iteration"); - return NULL; - } - if (PyDict_Next((PyObject *)(di->di_dict), &di->di_pos, &key, &value)) { - return (*di->di_select)(key, value); - } - PyErr_SetObject(PyExc_StopIteration, Py_None); - return NULL; -} - -static PyObject * dictiter_getiter(PyObject *it) { Py_INCREF(it); return it; } -static PyMethodDef dictiter_methods[] = { - {"next", (PyCFunction)dictiter_next, METH_VARARGS, - "it.next() -- get the next value, or raise StopIteration"}, - {NULL, NULL} /* sentinel */ -}; - static PyObject *dictiter_iternext(dictiterobject *di) { PyObject *key, *value; + if (di->di_dict == NULL) + return NULL; + if (di->di_used != di->di_dict->ma_used) { PyErr_SetString(PyExc_RuntimeError, "dictionary changed size during iteration"); + di->di_used = -1; /* Make this state sticky */ return NULL; } - if (PyDict_Next((PyObject *)(di->di_dict), &di->di_pos, &key, &value)) { + if (PyDict_Next((PyObject *)(di->di_dict), &di->di_pos, &key, &value)) return (*di->di_select)(key, value); - } + + Py_DECREF(di->di_dict); + di->di_dict = NULL; return NULL; } @@ -2019,7 +2002,7 @@ PyTypeObject PyDictIter_Type = { 0, /* tp_weaklistoffset */ (getiterfunc)dictiter_getiter, /* tp_iter */ (iternextfunc)dictiter_iternext, /* tp_iternext */ - dictiter_methods, /* tp_methods */ + 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ |