[Python-checkins] python/dist/src/Modules itertoolsmodule.c,1.5,1.6
rhettinger@users.sourceforge.net
rhettinger@users.sourceforge.net
2003年2月22日 20:40:09 -0800
Update of /cvsroot/python/python/dist/src/Modules
In directory sc8-pr-cvs1:/tmp/cvs-serv23087/Modules
Modified Files:
itertoolsmodule.c
Log Message:
User requested changes to the itertools module.
Subsumed times() into repeat().
Added cycle() and chain().
Index: itertoolsmodule.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/itertoolsmodule.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -C2 -d -r1.5 -r1.6
*** itertoolsmodule.c 9 Feb 2003 17:18:42 -0000 1.5
--- itertoolsmodule.c 23 Feb 2003 04:40:07 -0000 1.6
***************
*** 8,11 ****
--- 8,168 ----
*/
+ /* cycle object **********************************************************/
+
+ typedef struct {
+ PyObject_HEAD
+ PyObject *it;
+ PyObject *saved;
+ int firstpass;
+ } cycleobject;
+
+ PyTypeObject cycle_type;
+
+ static PyObject *
+ cycle_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+ {
+ PyObject *it;
+ PyObject *iterable;
+ PyObject *saved;
+ cycleobject *lz;
+
+ if (!PyArg_UnpackTuple(args, "cycle", 1, 1, &iterable))
+ return NULL;
+
+ /* Get iterator. */
+ it = PyObject_GetIter(iterable);
+ if (it == NULL)
+ return NULL;
+
+ saved = PyList_New(0);
+ if (saved == NULL) {
+ Py_DECREF(it);
+ return NULL;
+ }
+
+ /* create cycleobject structure */
+ lz = (cycleobject *)type->tp_alloc(type, 0);
+ if (lz == NULL) {
+ Py_DECREF(it);
+ Py_DECREF(saved);
+ return NULL;
+ }
+ lz->it = it;
+ lz->saved = saved;
+ lz->firstpass = 0;
+
+ return (PyObject *)lz;
+ }
+
+ static void
+ cycle_dealloc(cycleobject *lz)
+ {
+ PyObject_GC_UnTrack(lz);
+ Py_XDECREF(lz->saved);
+ Py_XDECREF(lz->it);
+ lz->ob_type->tp_free(lz);
+ }
+
+ static int
+ cycle_traverse(cycleobject *lz, visitproc visit, void *arg)
+ {
+ int err;
+
+ if (lz->it) {
+ err = visit(lz->it, arg);
+ if (err)
+ return err;
+ }
+ if (lz->saved) {
+ err = visit(lz->saved, arg);
+ if (err)
+ return err;
+ }
+ return 0;
+ }
+
+ static PyObject *
+ cycle_next(cycleobject *lz)
+ {
+ PyObject *item;
+ PyObject *it;
+
+ while (1) {
+ item = PyIter_Next(lz->it);
+ if (item != NULL) {
+ if (!lz->firstpass)
+ PyList_Append(lz->saved, item);
+ return item;
+ }
+ if (PyList_Size(lz->saved) == 0)
+ return NULL;
+ it = PyObject_GetIter(lz->saved);
+ if (it == NULL)
+ return NULL;
+ Py_DECREF(lz->it);
+ lz->it = it;
+ lz->firstpass = 1;
+ }
+ }
+
+ static PyObject *
+ cycle_getiter(PyObject *lz)
+ {
+ Py_INCREF(lz);
+ return lz;
+ }
+
+ PyDoc_STRVAR(cycle_doc,
+ "cycle(iterable) --> cycle object\n\
+ \n\
+ Return elements from the iterable until it is exhausted.\n\
+ Then repeat the sequence indefinitely.");
+
+ PyTypeObject cycle_type = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /* ob_size */
+ "itertools.cycle", /* tp_name */
+ sizeof(cycleobject), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ /* methods */
+ (destructor)cycle_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 */
+ cycle_doc, /* tp_doc */
+ (traverseproc)cycle_traverse, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ (getiterfunc)cycle_getiter, /* tp_iter */
+ (iternextfunc)cycle_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 */
+ cycle_new, /* tp_new */
+ PyObject_GC_Del, /* tp_free */
+ };
+
+
/* dropwhile object **********************************************************/
***************
*** 827,863 ****
! /* times object ************************************************************/
typedef struct {
PyObject_HEAD
! PyObject *obj;
! long cnt;
! } timesobject;
! PyTypeObject times_type;
static PyObject *
! times_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
! timesobject *lz;
! PyObject *obj = Py_None;
! long cnt;
!
! if (!PyArg_ParseTuple(args, "l|O:times", &cnt, &obj))
! return NULL;
! if (cnt < 0) {
! PyErr_SetString(PyExc_ValueError,
! "count for times() cannot be negative.");
return NULL;
}
! /* create timesobject structure */
! lz = (timesobject *)type->tp_alloc(type, 0);
if (lz == NULL)
return NULL;
! lz->cnt = cnt;
! Py_INCREF(obj);
! lz->obj = obj;
return (PyObject *)lz;
--- 984,1033 ----
! /* chain object ************************************************************/
typedef struct {
PyObject_HEAD
! long tuplesize;
! long iternum; /* which iterator is active */
! PyObject *ittuple; /* tuple of iterators */
! } chainobject;
! PyTypeObject chain_type;
static PyObject *
! chain_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
! chainobject *lz;
! int tuplesize = PySequence_Length(args);
! int i;
! PyObject *ittuple;
! /* obtain iterators */
! assert(PyTuple_Check(args));
! ittuple = PyTuple_New(tuplesize);
! if(ittuple == NULL)
return NULL;
+ for (i=0; i < tuplesize; ++i) {
+ PyObject *item = PyTuple_GET_ITEM(args, i);
+ PyObject *it = PyObject_GetIter(item);
+ if (it == NULL) {
+ if (PyErr_ExceptionMatches(PyExc_TypeError))
+ PyErr_Format(PyExc_TypeError,
+ "chain argument #%d must support iteration",
+ i+1);
+ Py_DECREF(ittuple);
+ return NULL;
+ }
+ PyTuple_SET_ITEM(ittuple, i, it);
}
! /* create chainobject structure */
! lz = (chainobject *)type->tp_alloc(type, 0);
if (lz == NULL)
return NULL;
!
! lz->ittuple = ittuple;
! lz->iternum = 0;
! lz->tuplesize = tuplesize;
return (PyObject *)lz;
***************
*** 865,892 ****
static void
! times_dealloc(timesobject *lz)
{
PyObject_GC_UnTrack(lz);
! Py_XDECREF(lz->obj);
lz->ob_type->tp_free(lz);
}
static int
! times_traverse(timesobject *lz, visitproc visit, void *arg)
{
! if (lz->obj)
! return visit(lz->obj, arg);
return 0;
}
static PyObject *
! times_next(timesobject *lz)
{
! PyObject *obj = lz->obj;
! if (lz->cnt > 0) {
! lz->cnt--;
! Py_INCREF(obj);
! return obj;
}
return NULL;
--- 1035,1065 ----
static void
! chain_dealloc(chainobject *lz)
{
PyObject_GC_UnTrack(lz);
! Py_XDECREF(lz->ittuple);
lz->ob_type->tp_free(lz);
}
static int
! chain_traverse(chainobject *lz, visitproc visit, void *arg)
{
! if (lz->ittuple)
! return visit(lz->ittuple, arg);
return 0;
}
static PyObject *
! chain_next(chainobject *lz)
{
! PyObject *it;
! PyObject *item;
! while (lz->iternum < lz->tuplesize) {
! it = PyTuple_GET_ITEM(lz->ittuple, lz->iternum);
! item = PyIter_Next(it);
! if (item != NULL)
! return item;
! lz->iternum++;
}
return NULL;
***************
*** 894,898 ****
static PyObject *
! times_getiter(PyObject *lz)
{
Py_INCREF(lz);
--- 1067,1071 ----
static PyObject *
! chain_getiter(PyObject *lz)
{
Py_INCREF(lz);
***************
*** 900,917 ****
}
! PyDoc_STRVAR(times_doc,
! "times(n [,obj]) --> times object\n\
\n\
! Return a times object whose .next() method returns n consecutive\n\
! instances of obj (default is None).");
! PyTypeObject times_type = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
! "itertools.times", /* tp_name */
! sizeof(timesobject), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
! (destructor)times_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
--- 1073,1091 ----
}
! PyDoc_STRVAR(chain_doc,
! "chain(*iterables) --> chain object\n\
\n\
! Return a chain object whose .next() method returns elements from the\n\
! first iterable until it is exhausted, then elements from the next\n\
! iterable, until all of the iterables are exhausted.");
! PyTypeObject chain_type = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
! "itertools.chain", /* tp_name */
! sizeof(chainobject), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
! (destructor)chain_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
***************
*** 930,940 ****
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_BASETYPE, /* tp_flags */
! times_doc, /* tp_doc */
! (traverseproc)times_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
! (getiterfunc)times_getiter, /* tp_iter */
! (iternextfunc)times_next, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
--- 1104,1114 ----
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_BASETYPE, /* tp_flags */
! chain_doc, /* tp_doc */
! (traverseproc)chain_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
! (getiterfunc)chain_getiter, /* tp_iter */
! (iternextfunc)chain_next, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
***************
*** 947,951 ****
0, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */
! times_new, /* tp_new */
PyObject_GC_Del, /* tp_free */
};
--- 1121,1125 ----
0, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */
! chain_new, /* tp_new */
PyObject_GC_Del, /* tp_free */
};
***************
*** 1545,1548 ****
--- 1719,1723 ----
PyObject_HEAD
PyObject *element;
+ long cnt;
} repeatobject;
***************
*** 1554,1559 ****
repeatobject *ro;
PyObject *element;
! if (!PyArg_UnpackTuple(args, "repeat", 1, 1, &element))
return NULL;
--- 1729,1735 ----
repeatobject *ro;
PyObject *element;
+ long cnt = -1;
! if (!PyArg_ParseTuple(args, "O|l:repeat", &element, &cnt))
return NULL;
***************
*** 1563,1566 ****
--- 1739,1743 ----
Py_INCREF(element);
ro->element = element;
+ ro->cnt = cnt;
return (PyObject *)ro;
}
***************
*** 1585,1588 ****
--- 1762,1769 ----
repeat_next(repeatobject *ro)
{
+ if (ro->cnt == 0)
+ return NULL;
+ if (ro->cnt > 0)
+ ro->cnt--;
Py_INCREF(ro->element);
return ro->element;
***************
*** 1597,1601 ****
PyDoc_STRVAR(repeat_doc,
! "repeat(element) -> create an iterator which returns the element endlessly.");
PyTypeObject repeat_type = {
--- 1778,1784 ----
PyDoc_STRVAR(repeat_doc,
! "repeat(element [,times]) -> create an iterator which returns the element\n\
! for the specified number of times. If not specified, returns the element\n\
! endlessly.");
PyTypeObject repeat_type = {
***************
*** 1652,1656 ****
Infinite iterators:\n\
count([n]) --> n, n+1, n+2, ...\n\
! repeat(elem) --> elem, elem, elem, ...\n\
\n\
Iterators terminating on the shortest input sequence:\n\
--- 1835,1840 ----
Infinite iterators:\n\
count([n]) --> n, n+1, n+2, ...\n\
! cycle(p) --> p0, p1, ... plast, p0, p1, ...\n\
! repeat(elem [,n]) --> elem, elem, elem, ... endlessly or upto n times\n\
\n\
Iterators terminating on the shortest input sequence:\n\
***************
*** 1662,1666 ****
imap(fun, p, q, ...) --> fun(p0, q0), fun(p1, q1), ...\n\
starmap(fun, seq) --> fun(*seq[0]), fun(*seq[1]), ...\n\
! times(n, [obj]) --> obj, obj, ... for n times. obj defaults to None\n\
takewhile(pred, seq) --> seq[0], seq[1], until pred fails\n\
dropwhile(pred, seq) --> seq[n], seq[n+1], starting when pred fails\n\
--- 1846,1850 ----
imap(fun, p, q, ...) --> fun(p0, q0), fun(p1, q1), ...\n\
starmap(fun, seq) --> fun(*seq[0]), fun(*seq[1]), ...\n\
! chain(p, q, ...) --> p0, p1, ... plast, q0, q1, ... \n\
takewhile(pred, seq) --> seq[0], seq[1], until pred fails\n\
dropwhile(pred, seq) --> seq[n], seq[n+1], starting when pred fails\n\
***************
*** 1675,1678 ****
--- 1859,1863 ----
char *name;
PyTypeObject *typelist[] = {
+ &cycle_type,
&dropwhile_type,
&takewhile_type,
***************
*** 1680,1684 ****
&starmap_type,
&imap_type,
! ×_type,
&ifilter_type,
&ifilterfalse_type,
--- 1865,1869 ----
&starmap_type,
&imap_type,
! &chain_type,
&ifilter_type,
&ifilterfalse_type,
***************
*** 1695,1700 ****
return;
name = strchr(typelist[i]->tp_name, '.') + 1;
! if (name == NULL)
! return;
Py_INCREF(typelist[i]);
PyModule_AddObject(m, name, (PyObject *)typelist[i]);
--- 1880,1884 ----
return;
name = strchr(typelist[i]->tp_name, '.') + 1;
! assert (name != NULL);
Py_INCREF(typelist[i]);
PyModule_AddObject(m, name, (PyObject *)typelist[i]);