cpython/Objects/enumobject.c
Guido van Rossum ca5ed5b875 Remove the next() method -- one is supplied automatically by
PyType_Ready() because the tp_iternext slot is set (fortunately,
because using the tp_iternext implementation for the the next()
implementation is buggy).  Also changed the allocation order in
enum_next() so that the underlying iterator is only moved ahead when
we have successfully allocated the result tuple and index.
2002-07-16 21:02:42 +00:00

135 lines
3.6 KiB
C

/* enumerate object */
#include "Python.h"
typedef struct {
PyObject_HEAD
long en_index; /* current index of enumeration */
PyObject* en_sit; /* secondary iterator of enumeration */
} enumobject;
PyTypeObject PyEnum_Type;
static PyObject *
enum_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
enumobject *en;
PyObject *seq = NULL;
static char *kwlist[] = {"sequence", 0};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:enumerate", kwlist,
&seq))
return NULL;
en = (enumobject *)type->tp_alloc(type, 0);
if (en == NULL)
return NULL;
en->en_index = 0;
en->en_sit = PyObject_GetIter(seq);
if (en->en_sit == NULL) {
Py_DECREF(en);
return NULL;
}
return (PyObject *)en;
}
static void
enum_dealloc(enumobject *en)
{
PyObject_GC_UnTrack(en);
Py_XDECREF(en->en_sit);
en->ob_type->tp_free(en);
}
static int
enum_traverse(enumobject *en, visitproc visit, void *arg)
{
if (en->en_sit)
return visit(en->en_sit, arg);
return 0;
}
static PyObject *
enum_next(enumobject *en)
{
PyObject *result;
PyObject *next_index;
PyObject *next_item;
result = PyTuple_New(2);
if (result == NULL)
return NULL;
next_index = PyInt_FromLong(en->en_index);
if (next_index == NULL) {
Py_DECREF(result);
return NULL;
}
PyTuple_SET_ITEM(result, 0, next_index);
next_item = PyIter_Next(en->en_sit);
if (next_item == NULL) {
Py_DECREF(result);
return NULL;
}
en->en_index++;
PyTuple_SET_ITEM(result, 1, next_item);
return result;
}
static PyObject *
enum_getiter(PyObject *en)
{
Py_INCREF(en);
return en;
}
PyDoc_STRVAR(enum_doc,
"enumerate(iterable) -> create an enumerating-iterator");
PyTypeObject PyEnum_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0, /* ob_size */
"enumerate", /* tp_name */
sizeof(enumobject), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor)enum_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_BASETYPE, /* tp_flags */
enum_doc, /* tp_doc */
(traverseproc)enum_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
(getiterfunc)enum_getiter, /* tp_iter */
(iternextfunc)enum_next, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */
enum_new, /* tp_new */
PyObject_GC_Del, /* tp_free */
};