You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
161 lines
4.7 KiB
161 lines
4.7 KiB
/* enumerate object */ |
|
|
|
#include "Python.h" |
|
|
|
typedef struct { |
|
PyObject_HEAD |
|
long en_index; /* current index of enumeration */ |
|
PyObject* en_sit; /* secondary iterator of enumeration */ |
|
PyObject* en_result; /* result tuple */ |
|
} 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; |
|
} |
|
en->en_result = PyTuple_New(2); |
|
if (en->en_result == NULL) { |
|
Py_DECREF(en->en_sit); |
|
Py_DECREF(en); |
|
return NULL; |
|
} |
|
Py_INCREF(Py_None); |
|
PyTuple_SET_ITEM(en->en_result, 0, Py_None); |
|
Py_INCREF(Py_None); |
|
PyTuple_SET_ITEM(en->en_result, 1, Py_None); |
|
return (PyObject *)en; |
|
} |
|
|
|
static void |
|
enum_dealloc(enumobject *en) |
|
{ |
|
PyObject_GC_UnTrack(en); |
|
Py_XDECREF(en->en_sit); |
|
Py_XDECREF(en->en_result); |
|
en->ob_type->tp_free(en); |
|
} |
|
|
|
static int |
|
enum_traverse(enumobject *en, visitproc visit, void *arg) |
|
{ |
|
int err; |
|
|
|
if (en->en_sit) { |
|
err = visit(en->en_sit, arg); |
|
if (err) |
|
return err; |
|
} |
|
if (en->en_result) { |
|
err = visit(en->en_result, arg); |
|
if (err) |
|
return err; |
|
} |
|
return 0; |
|
} |
|
|
|
static PyObject * |
|
enum_next(enumobject *en) |
|
{ |
|
PyObject *next_index; |
|
PyObject *next_item; |
|
PyObject *result = en->en_result; |
|
PyObject *it = en->en_sit; |
|
|
|
next_item = (*it->ob_type->tp_iternext)(it); |
|
if (next_item == NULL) |
|
return NULL; |
|
|
|
next_index = PyInt_FromLong(en->en_index); |
|
if (next_index == NULL) { |
|
Py_DECREF(next_item); |
|
return NULL; |
|
} |
|
en->en_index++; |
|
|
|
if (result->ob_refcnt == 1) { |
|
Py_INCREF(result); |
|
Py_DECREF(PyTuple_GET_ITEM(result, 0)); |
|
Py_DECREF(PyTuple_GET_ITEM(result, 1)); |
|
} else { |
|
result = PyTuple_New(2); |
|
if (result == NULL) { |
|
Py_DECREF(next_index); |
|
Py_DECREF(next_item); |
|
return NULL; |
|
} |
|
} |
|
PyTuple_SET_ITEM(result, 0, next_index); |
|
PyTuple_SET_ITEM(result, 1, next_item); |
|
return result; |
|
} |
|
|
|
PyDoc_STRVAR(enum_doc, |
|
"enumerate(iterable) -> iterator for index, value of iterable\n" |
|
"\n" |
|
"Return an enumerate object. iterable must be an other object that supports\n" |
|
"iteration. The enumerate object yields pairs containing a count (from\n" |
|
"zero) and a value yielded by the iterable argument. enumerate is useful\n" |
|
"for obtaining an indexed list: (0, seq[0]), (1, seq[1]), (2, seq[2]), ..."); |
|
|
|
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 */ |
|
PyObject_SelfIter, /* 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 */ |
|
};
|
|
|