+++ /dev/null
-\r
-#include "Python.h"\r
-#include "structmember.h"\r
-\r
-/* Itertools module written and maintained\r
- by Raymond D. Hettinger <python@rcn.com>\r
- Copyright (c) 2003 Python Software Foundation.\r
- All rights reserved.\r
-*/\r
-\r
-\r
-/* groupby object ***********************************************************/\r
-\r
-typedef struct {\r
- PyObject_HEAD\r
- PyObject *it;\r
- PyObject *keyfunc;\r
- PyObject *tgtkey;\r
- PyObject *currkey;\r
- PyObject *currvalue;\r
-} groupbyobject;\r
-\r
-static PyTypeObject groupby_type;\r
-static PyObject *_grouper_create(groupbyobject *, PyObject *);\r
-\r
-static PyObject *\r
-groupby_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
-{\r
- static char *kwargs[] = {"iterable", "key", NULL};\r
- groupbyobject *gbo;\r
- PyObject *it, *keyfunc = Py_None;\r
-\r
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:groupby", kwargs,\r
- &it, &keyfunc))\r
- return NULL;\r
-\r
- gbo = (groupbyobject *)type->tp_alloc(type, 0);\r
- if (gbo == NULL)\r
- return NULL;\r
- gbo->tgtkey = NULL;\r
- gbo->currkey = NULL;\r
- gbo->currvalue = NULL;\r
- gbo->keyfunc = keyfunc;\r
- Py_INCREF(keyfunc);\r
- gbo->it = PyObject_GetIter(it);\r
- if (gbo->it == NULL) {\r
- Py_DECREF(gbo);\r
- return NULL;\r
- }\r
- return (PyObject *)gbo;\r
-}\r
-\r
-static void\r
-groupby_dealloc(groupbyobject *gbo)\r
-{\r
- PyObject_GC_UnTrack(gbo);\r
- Py_XDECREF(gbo->it);\r
- Py_XDECREF(gbo->keyfunc);\r
- Py_XDECREF(gbo->tgtkey);\r
- Py_XDECREF(gbo->currkey);\r
- Py_XDECREF(gbo->currvalue);\r
- Py_TYPE(gbo)->tp_free(gbo);\r
-}\r
-\r
-static int\r
-groupby_traverse(groupbyobject *gbo, visitproc visit, void *arg)\r
-{\r
- Py_VISIT(gbo->it);\r
- Py_VISIT(gbo->keyfunc);\r
- Py_VISIT(gbo->tgtkey);\r
- Py_VISIT(gbo->currkey);\r
- Py_VISIT(gbo->currvalue);\r
- return 0;\r
-}\r
-\r
-static PyObject *\r
-groupby_next(groupbyobject *gbo)\r
-{\r
- PyObject *newvalue, *newkey, *r, *grouper, *tmp;\r
-\r
- /* skip to next iteration group */\r
- for (;;) {\r
- if (gbo->currkey == NULL)\r
- /* pass */;\r
- else if (gbo->tgtkey == NULL)\r
- break;\r
- else {\r
- int rcmp;\r
-\r
- rcmp = PyObject_RichCompareBool(gbo->tgtkey,\r
- gbo->currkey, Py_EQ);\r
- if (rcmp == -1)\r
- return NULL;\r
- else if (rcmp == 0)\r
- break;\r
- }\r
-\r
- newvalue = PyIter_Next(gbo->it);\r
- if (newvalue == NULL)\r
- return NULL;\r
-\r
- if (gbo->keyfunc == Py_None) {\r
- newkey = newvalue;\r
- Py_INCREF(newvalue);\r
- } else {\r
- newkey = PyObject_CallFunctionObjArgs(gbo->keyfunc,\r
- newvalue, NULL);\r
- if (newkey == NULL) {\r
- Py_DECREF(newvalue);\r
- return NULL;\r
- }\r
- }\r
-\r
- tmp = gbo->currkey;\r
- gbo->currkey = newkey;\r
- Py_XDECREF(tmp);\r
-\r
- tmp = gbo->currvalue;\r
- gbo->currvalue = newvalue;\r
- Py_XDECREF(tmp);\r
- }\r
-\r
- Py_INCREF(gbo->currkey);\r
- tmp = gbo->tgtkey;\r
- gbo->tgtkey = gbo->currkey;\r
- Py_XDECREF(tmp);\r
-\r
- grouper = _grouper_create(gbo, gbo->tgtkey);\r
- if (grouper == NULL)\r
- return NULL;\r
-\r
- r = PyTuple_Pack(2, gbo->currkey, grouper);\r
- Py_DECREF(grouper);\r
- return r;\r
-}\r
-\r
-PyDoc_STRVAR(groupby_doc,\r
-"groupby(iterable[, keyfunc]) -> create an iterator which returns\n\\r
-(key, sub-iterator) grouped by each value of key(value).\n");\r
-\r
-static PyTypeObject groupby_type = {\r
- PyVarObject_HEAD_INIT(NULL, 0)\r
- "itertools.groupby", /* tp_name */\r
- sizeof(groupbyobject), /* tp_basicsize */\r
- 0, /* tp_itemsize */\r
- /* methods */\r
- (destructor)groupby_dealloc, /* tp_dealloc */\r
- 0, /* tp_print */\r
- 0, /* tp_getattr */\r
- 0, /* tp_setattr */\r
- 0, /* tp_compare */\r
- 0, /* tp_repr */\r
- 0, /* tp_as_number */\r
- 0, /* tp_as_sequence */\r
- 0, /* tp_as_mapping */\r
- 0, /* tp_hash */\r
- 0, /* tp_call */\r
- 0, /* tp_str */\r
- PyObject_GenericGetAttr, /* tp_getattro */\r
- 0, /* tp_setattro */\r
- 0, /* tp_as_buffer */\r
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |\r
- Py_TPFLAGS_BASETYPE, /* tp_flags */\r
- groupby_doc, /* tp_doc */\r
- (traverseproc)groupby_traverse, /* tp_traverse */\r
- 0, /* tp_clear */\r
- 0, /* tp_richcompare */\r
- 0, /* tp_weaklistoffset */\r
- PyObject_SelfIter, /* tp_iter */\r
- (iternextfunc)groupby_next, /* tp_iternext */\r
- 0, /* tp_methods */\r
- 0, /* tp_members */\r
- 0, /* tp_getset */\r
- 0, /* tp_base */\r
- 0, /* tp_dict */\r
- 0, /* tp_descr_get */\r
- 0, /* tp_descr_set */\r
- 0, /* tp_dictoffset */\r
- 0, /* tp_init */\r
- 0, /* tp_alloc */\r
- groupby_new, /* tp_new */\r
- PyObject_GC_Del, /* tp_free */\r
-};\r
-\r
-\r
-/* _grouper object (internal) ************************************************/\r
-\r
-typedef struct {\r
- PyObject_HEAD\r
- PyObject *parent;\r
- PyObject *tgtkey;\r
-} _grouperobject;\r
-\r
-static PyTypeObject _grouper_type;\r
-\r
-static PyObject *\r
-_grouper_create(groupbyobject *parent, PyObject *tgtkey)\r
-{\r
- _grouperobject *igo;\r
-\r
- igo = PyObject_GC_New(_grouperobject, &_grouper_type);\r
- if (igo == NULL)\r
- return NULL;\r
- igo->parent = (PyObject *)parent;\r
- Py_INCREF(parent);\r
- igo->tgtkey = tgtkey;\r
- Py_INCREF(tgtkey);\r
-\r
- PyObject_GC_Track(igo);\r
- return (PyObject *)igo;\r
-}\r
-\r
-static void\r
-_grouper_dealloc(_grouperobject *igo)\r
-{\r
- PyObject_GC_UnTrack(igo);\r
- Py_DECREF(igo->parent);\r
- Py_DECREF(igo->tgtkey);\r
- PyObject_GC_Del(igo);\r
-}\r
-\r
-static int\r
-_grouper_traverse(_grouperobject *igo, visitproc visit, void *arg)\r
-{\r
- Py_VISIT(igo->parent);\r
- Py_VISIT(igo->tgtkey);\r
- return 0;\r
-}\r
-\r
-static PyObject *\r
-_grouper_next(_grouperobject *igo)\r
-{\r
- groupbyobject *gbo = (groupbyobject *)igo->parent;\r
- PyObject *newvalue, *newkey, *r;\r
- int rcmp;\r
-\r
- if (gbo->currvalue == NULL) {\r
- newvalue = PyIter_Next(gbo->it);\r
- if (newvalue == NULL)\r
- return NULL;\r
-\r
- if (gbo->keyfunc == Py_None) {\r
- newkey = newvalue;\r
- Py_INCREF(newvalue);\r
- } else {\r
- newkey = PyObject_CallFunctionObjArgs(gbo->keyfunc,\r
- newvalue, NULL);\r
- if (newkey == NULL) {\r
- Py_DECREF(newvalue);\r
- return NULL;\r
- }\r
- }\r
-\r
- assert(gbo->currkey == NULL);\r
- gbo->currkey = newkey;\r
- gbo->currvalue = newvalue;\r
- }\r
-\r
- assert(gbo->currkey != NULL);\r
- rcmp = PyObject_RichCompareBool(igo->tgtkey, gbo->currkey, Py_EQ);\r
- if (rcmp <= 0)\r
- /* got any error or current group is end */\r
- return NULL;\r
-\r
- r = gbo->currvalue;\r
- gbo->currvalue = NULL;\r
- Py_CLEAR(gbo->currkey);\r
-\r
- return r;\r
-}\r
-\r
-static PyTypeObject _grouper_type = {\r
- PyVarObject_HEAD_INIT(NULL, 0)\r
- "itertools._grouper", /* tp_name */\r
- sizeof(_grouperobject), /* tp_basicsize */\r
- 0, /* tp_itemsize */\r
- /* methods */\r
- (destructor)_grouper_dealloc, /* tp_dealloc */\r
- 0, /* tp_print */\r
- 0, /* tp_getattr */\r
- 0, /* tp_setattr */\r
- 0, /* tp_compare */\r
- 0, /* tp_repr */\r
- 0, /* tp_as_number */\r
- 0, /* tp_as_sequence */\r
- 0, /* tp_as_mapping */\r
- 0, /* tp_hash */\r
- 0, /* tp_call */\r
- 0, /* tp_str */\r
- PyObject_GenericGetAttr, /* tp_getattro */\r
- 0, /* tp_setattro */\r
- 0, /* tp_as_buffer */\r
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */\r
- 0, /* tp_doc */\r
- (traverseproc)_grouper_traverse,/* tp_traverse */\r
- 0, /* tp_clear */\r
- 0, /* tp_richcompare */\r
- 0, /* tp_weaklistoffset */\r
- PyObject_SelfIter, /* tp_iter */\r
- (iternextfunc)_grouper_next, /* tp_iternext */\r
- 0, /* tp_methods */\r
- 0, /* tp_members */\r
- 0, /* tp_getset */\r
- 0, /* tp_base */\r
- 0, /* tp_dict */\r
- 0, /* tp_descr_get */\r
- 0, /* tp_descr_set */\r
- 0, /* tp_dictoffset */\r
- 0, /* tp_init */\r
- 0, /* tp_alloc */\r
- 0, /* tp_new */\r
- PyObject_GC_Del, /* tp_free */\r
-};\r
-\r
-\r
-\r
-/* tee object and with supporting function and objects ***************/\r
-\r
-/* The teedataobject pre-allocates space for LINKCELLS number of objects.\r
- To help the object fit neatly inside cache lines (space for 16 to 32\r
- pointers), the value should be a multiple of 16 minus space for\r
- the other structure members including PyHEAD overhead. The larger the\r
- value, the less memory overhead per object and the less time spent\r
- allocating/deallocating new links. The smaller the number, the less\r
- wasted space and the more rapid freeing of older data.\r
-*/\r
-#define LINKCELLS 57\r
-\r
-typedef struct {\r
- PyObject_HEAD\r
- PyObject *it;\r
- int numread;\r
- PyObject *nextlink;\r
- PyObject *(values[LINKCELLS]);\r
-} teedataobject;\r
-\r
-typedef struct {\r
- PyObject_HEAD\r
- teedataobject *dataobj;\r
- int index;\r
- PyObject *weakreflist;\r
-} teeobject;\r
-\r
-static PyTypeObject teedataobject_type;\r
-\r
-static PyObject *\r
-teedataobject_new(PyObject *it)\r
-{\r
- teedataobject *tdo;\r
-\r
- tdo = PyObject_GC_New(teedataobject, &teedataobject_type);\r
- if (tdo == NULL)\r
- return NULL;\r
-\r
- tdo->numread = 0;\r
- tdo->nextlink = NULL;\r
- Py_INCREF(it);\r
- tdo->it = it;\r
- PyObject_GC_Track(tdo);\r
- return (PyObject *)tdo;\r
-}\r
-\r
-static PyObject *\r
-teedataobject_jumplink(teedataobject *tdo)\r
-{\r
- if (tdo->nextlink == NULL)\r
- tdo->nextlink = teedataobject_new(tdo->it);\r
- Py_XINCREF(tdo->nextlink);\r
- return tdo->nextlink;\r
-}\r
-\r
-static PyObject *\r
-teedataobject_getitem(teedataobject *tdo, int i)\r
-{\r
- PyObject *value;\r
-\r
- assert(i < LINKCELLS);\r
- if (i < tdo->numread)\r
- value = tdo->values[i];\r
- else {\r
- /* this is the lead iterator, so fetch more data */\r
- assert(i == tdo->numread);\r
- value = PyIter_Next(tdo->it);\r
- if (value == NULL)\r
- return NULL;\r
- tdo->numread++;\r
- tdo->values[i] = value;\r
- }\r
- Py_INCREF(value);\r
- return value;\r
-}\r
-\r
-static int\r
-teedataobject_traverse(teedataobject *tdo, visitproc visit, void * arg)\r
-{\r
- int i;\r
- Py_VISIT(tdo->it);\r
- for (i = 0; i < tdo->numread; i++)\r
- Py_VISIT(tdo->values[i]);\r
- Py_VISIT(tdo->nextlink);\r
- return 0;\r
-}\r
-\r
-static void\r
-teedataobject_safe_decref(PyObject *obj)\r
-{\r
- while (obj && Py_TYPE(obj) == &teedataobject_type &&\r
- Py_REFCNT(obj) == 1) {\r
- PyObject *nextlink = ((teedataobject *)obj)->nextlink;\r
- ((teedataobject *)obj)->nextlink = NULL;\r
- Py_DECREF(obj);\r
- obj = nextlink;\r
- }\r
- Py_XDECREF(obj);\r
-}\r
-\r
-static int\r
-teedataobject_clear(teedataobject *tdo)\r
-{\r
- int i;\r
- PyObject *tmp;\r
-\r
- Py_CLEAR(tdo->it);\r
- for (i=0 ; i<tdo->numread ; i++)\r
- Py_CLEAR(tdo->values[i]);\r
- tmp = tdo->nextlink;\r
- tdo->nextlink = NULL;\r
- teedataobject_safe_decref(tmp);\r
- return 0;\r
-}\r
-\r
-static void\r
-teedataobject_dealloc(teedataobject *tdo)\r
-{\r
- PyObject_GC_UnTrack(tdo);\r
- teedataobject_clear(tdo);\r
- PyObject_GC_Del(tdo);\r
-}\r
-\r
-PyDoc_STRVAR(teedataobject_doc, "Data container common to multiple tee objects.");\r
-\r
-static PyTypeObject teedataobject_type = {\r
- PyVarObject_HEAD_INIT(0, 0) /* Must fill in type value later */\r
- "itertools.tee_dataobject", /* tp_name */\r
- sizeof(teedataobject), /* tp_basicsize */\r
- 0, /* tp_itemsize */\r
- /* methods */\r
- (destructor)teedataobject_dealloc, /* tp_dealloc */\r
- 0, /* tp_print */\r
- 0, /* tp_getattr */\r
- 0, /* tp_setattr */\r
- 0, /* tp_compare */\r
- 0, /* tp_repr */\r
- 0, /* tp_as_number */\r
- 0, /* tp_as_sequence */\r
- 0, /* tp_as_mapping */\r
- 0, /* tp_hash */\r
- 0, /* tp_call */\r
- 0, /* tp_str */\r
- PyObject_GenericGetAttr, /* tp_getattro */\r
- 0, /* tp_setattro */\r
- 0, /* tp_as_buffer */\r
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */\r
- teedataobject_doc, /* tp_doc */\r
- (traverseproc)teedataobject_traverse, /* tp_traverse */\r
- (inquiry)teedataobject_clear, /* tp_clear */\r
- 0, /* tp_richcompare */\r
- 0, /* tp_weaklistoffset */\r
- 0, /* tp_iter */\r
- 0, /* tp_iternext */\r
- 0, /* tp_methods */\r
- 0, /* tp_members */\r
- 0, /* tp_getset */\r
- 0, /* tp_base */\r
- 0, /* tp_dict */\r
- 0, /* tp_descr_get */\r
- 0, /* tp_descr_set */\r
- 0, /* tp_dictoffset */\r
- 0, /* tp_init */\r
- 0, /* tp_alloc */\r
- 0, /* tp_new */\r
- PyObject_GC_Del, /* tp_free */\r
-};\r
-\r
-\r
-static PyTypeObject tee_type;\r
-\r
-static PyObject *\r
-tee_next(teeobject *to)\r
-{\r
- PyObject *value, *link;\r
-\r
- if (to->index >= LINKCELLS) {\r
- link = teedataobject_jumplink(to->dataobj);\r
- if (link == NULL)\r
- return NULL;\r
- Py_DECREF(to->dataobj);\r
- to->dataobj = (teedataobject *)link;\r
- to->index = 0;\r
- }\r
- value = teedataobject_getitem(to->dataobj, to->index);\r
- if (value == NULL)\r
- return NULL;\r
- to->index++;\r
- return value;\r
-}\r
-\r
-static int\r
-tee_traverse(teeobject *to, visitproc visit, void *arg)\r
-{\r
- Py_VISIT((PyObject *)to->dataobj);\r
- return 0;\r
-}\r
-\r
-static PyObject *\r
-tee_copy(teeobject *to)\r
-{\r
- teeobject *newto;\r
-\r
- newto = PyObject_GC_New(teeobject, &tee_type);\r
- if (newto == NULL)\r
- return NULL;\r
- Py_INCREF(to->dataobj);\r
- newto->dataobj = to->dataobj;\r
- newto->index = to->index;\r
- newto->weakreflist = NULL;\r
- PyObject_GC_Track(newto);\r
- return (PyObject *)newto;\r
-}\r
-\r
-PyDoc_STRVAR(teecopy_doc, "Returns an independent iterator.");\r
-\r
-static PyObject *\r
-tee_fromiterable(PyObject *iterable)\r
-{\r
- teeobject *to;\r
- PyObject *it = NULL;\r
-\r
- it = PyObject_GetIter(iterable);\r
- if (it == NULL)\r
- return NULL;\r
- if (PyObject_TypeCheck(it, &tee_type)) {\r
- to = (teeobject *)tee_copy((teeobject *)it);\r
- goto done;\r
- }\r
-\r
- to = PyObject_GC_New(teeobject, &tee_type);\r
- if (to == NULL)\r
- goto done;\r
- to->dataobj = (teedataobject *)teedataobject_new(it);\r
- if (!to->dataobj) {\r
- PyObject_GC_Del(to);\r
- to = NULL;\r
- goto done;\r
- }\r
-\r
- to->index = 0;\r
- to->weakreflist = NULL;\r
- PyObject_GC_Track(to);\r
-done:\r
- Py_XDECREF(it);\r
- return (PyObject *)to;\r
-}\r
-\r
-static PyObject *\r
-tee_new(PyTypeObject *type, PyObject *args, PyObject *kw)\r
-{\r
- PyObject *iterable;\r
-\r
- if (!PyArg_UnpackTuple(args, "tee", 1, 1, &iterable))\r
- return NULL;\r
- return tee_fromiterable(iterable);\r
-}\r
-\r
-static int\r
-tee_clear(teeobject *to)\r
-{\r
- if (to->weakreflist != NULL)\r
- PyObject_ClearWeakRefs((PyObject *) to);\r
- Py_CLEAR(to->dataobj);\r
- return 0;\r
-}\r
-\r
-static void\r
-tee_dealloc(teeobject *to)\r
-{\r
- PyObject_GC_UnTrack(to);\r
- tee_clear(to);\r
- PyObject_GC_Del(to);\r
-}\r
-\r
-PyDoc_STRVAR(teeobject_doc,\r
-"Iterator wrapped to make it copyable");\r
-\r
-static PyMethodDef tee_methods[] = {\r
- {"__copy__", (PyCFunction)tee_copy, METH_NOARGS, teecopy_doc},\r
- {NULL, NULL} /* sentinel */\r
-};\r
-\r
-static PyTypeObject tee_type = {\r
- PyVarObject_HEAD_INIT(NULL, 0)\r
- "itertools.tee", /* tp_name */\r
- sizeof(teeobject), /* tp_basicsize */\r
- 0, /* tp_itemsize */\r
- /* methods */\r
- (destructor)tee_dealloc, /* tp_dealloc */\r
- 0, /* tp_print */\r
- 0, /* tp_getattr */\r
- 0, /* tp_setattr */\r
- 0, /* tp_compare */\r
- 0, /* tp_repr */\r
- 0, /* tp_as_number */\r
- 0, /* tp_as_sequence */\r
- 0, /* tp_as_mapping */\r
- 0, /* tp_hash */\r
- 0, /* tp_call */\r
- 0, /* tp_str */\r
- 0, /* tp_getattro */\r
- 0, /* tp_setattro */\r
- 0, /* tp_as_buffer */\r
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */\r
- teeobject_doc, /* tp_doc */\r
- (traverseproc)tee_traverse, /* tp_traverse */\r
- (inquiry)tee_clear, /* tp_clear */\r
- 0, /* tp_richcompare */\r
- offsetof(teeobject, weakreflist), /* tp_weaklistoffset */\r
- PyObject_SelfIter, /* tp_iter */\r
- (iternextfunc)tee_next, /* tp_iternext */\r
- tee_methods, /* tp_methods */\r
- 0, /* tp_members */\r
- 0, /* tp_getset */\r
- 0, /* tp_base */\r
- 0, /* tp_dict */\r
- 0, /* tp_descr_get */\r
- 0, /* tp_descr_set */\r
- 0, /* tp_dictoffset */\r
- 0, /* tp_init */\r
- 0, /* tp_alloc */\r
- tee_new, /* tp_new */\r
- PyObject_GC_Del, /* tp_free */\r
-};\r
-\r
-static PyObject *\r
-tee(PyObject *self, PyObject *args)\r
-{\r
- Py_ssize_t i, n=2;\r
- PyObject *it, *iterable, *copyable, *result;\r
-\r
- if (!PyArg_ParseTuple(args, "O|n", &iterable, &n))\r
- return NULL;\r
- if (n < 0) {\r
- PyErr_SetString(PyExc_ValueError, "n must be >= 0");\r
- return NULL;\r
- }\r
- result = PyTuple_New(n);\r
- if (result == NULL)\r
- return NULL;\r
- if (n == 0)\r
- return result;\r
- it = PyObject_GetIter(iterable);\r
- if (it == NULL) {\r
- Py_DECREF(result);\r
- return NULL;\r
- }\r
- if (!PyObject_HasAttrString(it, "__copy__")) {\r
- copyable = tee_fromiterable(it);\r
- Py_DECREF(it);\r
- if (copyable == NULL) {\r
- Py_DECREF(result);\r
- return NULL;\r
- }\r
- } else\r
- copyable = it;\r
- PyTuple_SET_ITEM(result, 0, copyable);\r
- for (i=1 ; i<n ; i++) {\r
- copyable = PyObject_CallMethod(copyable, "__copy__", NULL);\r
- if (copyable == NULL) {\r
- Py_DECREF(result);\r
- return NULL;\r
- }\r
- PyTuple_SET_ITEM(result, i, copyable);\r
- }\r
- return result;\r
-}\r
-\r
-PyDoc_STRVAR(tee_doc,\r
-"tee(iterable, n=2) --> tuple of n independent iterators.");\r
-\r
-\r
-/* cycle object **********************************************************/\r
-\r
-typedef struct {\r
- PyObject_HEAD\r
- PyObject *it;\r
- PyObject *saved;\r
- int firstpass;\r
-} cycleobject;\r
-\r
-static PyTypeObject cycle_type;\r
-\r
-static PyObject *\r
-cycle_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
-{\r
- PyObject *it;\r
- PyObject *iterable;\r
- PyObject *saved;\r
- cycleobject *lz;\r
-\r
- if (type == &cycle_type && !_PyArg_NoKeywords("cycle()", kwds))\r
- return NULL;\r
-\r
- if (!PyArg_UnpackTuple(args, "cycle", 1, 1, &iterable))\r
- return NULL;\r
-\r
- /* Get iterator. */\r
- it = PyObject_GetIter(iterable);\r
- if (it == NULL)\r
- return NULL;\r
-\r
- saved = PyList_New(0);\r
- if (saved == NULL) {\r
- Py_DECREF(it);\r
- return NULL;\r
- }\r
-\r
- /* create cycleobject structure */\r
- lz = (cycleobject *)type->tp_alloc(type, 0);\r
- if (lz == NULL) {\r
- Py_DECREF(it);\r
- Py_DECREF(saved);\r
- return NULL;\r
- }\r
- lz->it = it;\r
- lz->saved = saved;\r
- lz->firstpass = 0;\r
-\r
- return (PyObject *)lz;\r
-}\r
-\r
-static void\r
-cycle_dealloc(cycleobject *lz)\r
-{\r
- PyObject_GC_UnTrack(lz);\r
- Py_XDECREF(lz->saved);\r
- Py_XDECREF(lz->it);\r
- Py_TYPE(lz)->tp_free(lz);\r
-}\r
-\r
-static int\r
-cycle_traverse(cycleobject *lz, visitproc visit, void *arg)\r
-{\r
- Py_VISIT(lz->it);\r
- Py_VISIT(lz->saved);\r
- return 0;\r
-}\r
-\r
-static PyObject *\r
-cycle_next(cycleobject *lz)\r
-{\r
- PyObject *item;\r
- PyObject *it;\r
- PyObject *tmp;\r
-\r
- while (1) {\r
- item = PyIter_Next(lz->it);\r
- if (item != NULL) {\r
- if (!lz->firstpass && PyList_Append(lz->saved, item)) {\r
- Py_DECREF(item);\r
- return NULL;\r
- }\r
- return item;\r
- }\r
- if (PyErr_Occurred()) {\r
- if (PyErr_ExceptionMatches(PyExc_StopIteration))\r
- PyErr_Clear();\r
- else\r
- return NULL;\r
- }\r
- if (PyList_Size(lz->saved) == 0)\r
- return NULL;\r
- it = PyObject_GetIter(lz->saved);\r
- if (it == NULL)\r
- return NULL;\r
- tmp = lz->it;\r
- lz->it = it;\r
- lz->firstpass = 1;\r
- Py_DECREF(tmp);\r
- }\r
-}\r
-\r
-PyDoc_STRVAR(cycle_doc,\r
-"cycle(iterable) --> cycle object\n\\r
-\n\\r
-Return elements from the iterable until it is exhausted.\n\\r
-Then repeat the sequence indefinitely.");\r
-\r
-static PyTypeObject cycle_type = {\r
- PyVarObject_HEAD_INIT(NULL, 0)\r
- "itertools.cycle", /* tp_name */\r
- sizeof(cycleobject), /* tp_basicsize */\r
- 0, /* tp_itemsize */\r
- /* methods */\r
- (destructor)cycle_dealloc, /* tp_dealloc */\r
- 0, /* tp_print */\r
- 0, /* tp_getattr */\r
- 0, /* tp_setattr */\r
- 0, /* tp_compare */\r
- 0, /* tp_repr */\r
- 0, /* tp_as_number */\r
- 0, /* tp_as_sequence */\r
- 0, /* tp_as_mapping */\r
- 0, /* tp_hash */\r
- 0, /* tp_call */\r
- 0, /* tp_str */\r
- PyObject_GenericGetAttr, /* tp_getattro */\r
- 0, /* tp_setattro */\r
- 0, /* tp_as_buffer */\r
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |\r
- Py_TPFLAGS_BASETYPE, /* tp_flags */\r
- cycle_doc, /* tp_doc */\r
- (traverseproc)cycle_traverse, /* tp_traverse */\r
- 0, /* tp_clear */\r
- 0, /* tp_richcompare */\r
- 0, /* tp_weaklistoffset */\r
- PyObject_SelfIter, /* tp_iter */\r
- (iternextfunc)cycle_next, /* tp_iternext */\r
- 0, /* tp_methods */\r
- 0, /* tp_members */\r
- 0, /* tp_getset */\r
- 0, /* tp_base */\r
- 0, /* tp_dict */\r
- 0, /* tp_descr_get */\r
- 0, /* tp_descr_set */\r
- 0, /* tp_dictoffset */\r
- 0, /* tp_init */\r
- 0, /* tp_alloc */\r
- cycle_new, /* tp_new */\r
- PyObject_GC_Del, /* tp_free */\r
-};\r
-\r
-\r
-/* dropwhile object **********************************************************/\r
-\r
-typedef struct {\r
- PyObject_HEAD\r
- PyObject *func;\r
- PyObject *it;\r
- long start;\r
-} dropwhileobject;\r
-\r
-static PyTypeObject dropwhile_type;\r
-\r
-static PyObject *\r
-dropwhile_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
-{\r
- PyObject *func, *seq;\r
- PyObject *it;\r
- dropwhileobject *lz;\r
-\r
- if (type == &dropwhile_type && !_PyArg_NoKeywords("dropwhile()", kwds))\r
- return NULL;\r
-\r
- if (!PyArg_UnpackTuple(args, "dropwhile", 2, 2, &func, &seq))\r
- return NULL;\r
-\r
- /* Get iterator. */\r
- it = PyObject_GetIter(seq);\r
- if (it == NULL)\r
- return NULL;\r
-\r
- /* create dropwhileobject structure */\r
- lz = (dropwhileobject *)type->tp_alloc(type, 0);\r
- if (lz == NULL) {\r
- Py_DECREF(it);\r
- return NULL;\r
- }\r
- Py_INCREF(func);\r
- lz->func = func;\r
- lz->it = it;\r
- lz->start = 0;\r
-\r
- return (PyObject *)lz;\r
-}\r
-\r
-static void\r
-dropwhile_dealloc(dropwhileobject *lz)\r
-{\r
- PyObject_GC_UnTrack(lz);\r
- Py_XDECREF(lz->func);\r
- Py_XDECREF(lz->it);\r
- Py_TYPE(lz)->tp_free(lz);\r
-}\r
-\r
-static int\r
-dropwhile_traverse(dropwhileobject *lz, visitproc visit, void *arg)\r
-{\r
- Py_VISIT(lz->it);\r
- Py_VISIT(lz->func);\r
- return 0;\r
-}\r
-\r
-static PyObject *\r
-dropwhile_next(dropwhileobject *lz)\r
-{\r
- PyObject *item, *good;\r
- PyObject *it = lz->it;\r
- long ok;\r
- PyObject *(*iternext)(PyObject *);\r
-\r
- iternext = *Py_TYPE(it)->tp_iternext;\r
- for (;;) {\r
- item = iternext(it);\r
- if (item == NULL)\r
- return NULL;\r
- if (lz->start == 1)\r
- return item;\r
-\r
- good = PyObject_CallFunctionObjArgs(lz->func, item, NULL);\r
- if (good == NULL) {\r
- Py_DECREF(item);\r
- return NULL;\r
- }\r
- ok = PyObject_IsTrue(good);\r
- Py_DECREF(good);\r
- if (ok == 0) {\r
- lz->start = 1;\r
- return item;\r
- }\r
- Py_DECREF(item);\r
- if (ok < 0)\r
- return NULL;\r
- }\r
-}\r
-\r
-PyDoc_STRVAR(dropwhile_doc,\r
-"dropwhile(predicate, iterable) --> dropwhile object\n\\r
-\n\\r
-Drop items from the iterable while predicate(item) is true.\n\\r
-Afterwards, return every element until the iterable is exhausted.");\r
-\r
-static PyTypeObject dropwhile_type = {\r
- PyVarObject_HEAD_INIT(NULL, 0)\r
- "itertools.dropwhile", /* tp_name */\r
- sizeof(dropwhileobject), /* tp_basicsize */\r
- 0, /* tp_itemsize */\r
- /* methods */\r
- (destructor)dropwhile_dealloc, /* tp_dealloc */\r
- 0, /* tp_print */\r
- 0, /* tp_getattr */\r
- 0, /* tp_setattr */\r
- 0, /* tp_compare */\r
- 0, /* tp_repr */\r
- 0, /* tp_as_number */\r
- 0, /* tp_as_sequence */\r
- 0, /* tp_as_mapping */\r
- 0, /* tp_hash */\r
- 0, /* tp_call */\r
- 0, /* tp_str */\r
- PyObject_GenericGetAttr, /* tp_getattro */\r
- 0, /* tp_setattro */\r
- 0, /* tp_as_buffer */\r
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |\r
- Py_TPFLAGS_BASETYPE, /* tp_flags */\r
- dropwhile_doc, /* tp_doc */\r
- (traverseproc)dropwhile_traverse, /* tp_traverse */\r
- 0, /* tp_clear */\r
- 0, /* tp_richcompare */\r
- 0, /* tp_weaklistoffset */\r
- PyObject_SelfIter, /* tp_iter */\r
- (iternextfunc)dropwhile_next, /* tp_iternext */\r
- 0, /* tp_methods */\r
- 0, /* tp_members */\r
- 0, /* tp_getset */\r
- 0, /* tp_base */\r
- 0, /* tp_dict */\r
- 0, /* tp_descr_get */\r
- 0, /* tp_descr_set */\r
- 0, /* tp_dictoffset */\r
- 0, /* tp_init */\r
- 0, /* tp_alloc */\r
- dropwhile_new, /* tp_new */\r
- PyObject_GC_Del, /* tp_free */\r
-};\r
-\r
-\r
-/* takewhile object **********************************************************/\r
-\r
-typedef struct {\r
- PyObject_HEAD\r
- PyObject *func;\r
- PyObject *it;\r
- long stop;\r
-} takewhileobject;\r
-\r
-static PyTypeObject takewhile_type;\r
-\r
-static PyObject *\r
-takewhile_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
-{\r
- PyObject *func, *seq;\r
- PyObject *it;\r
- takewhileobject *lz;\r
-\r
- if (type == &takewhile_type && !_PyArg_NoKeywords("takewhile()", kwds))\r
- return NULL;\r
-\r
- if (!PyArg_UnpackTuple(args, "takewhile", 2, 2, &func, &seq))\r
- return NULL;\r
-\r
- /* Get iterator. */\r
- it = PyObject_GetIter(seq);\r
- if (it == NULL)\r
- return NULL;\r
-\r
- /* create takewhileobject structure */\r
- lz = (takewhileobject *)type->tp_alloc(type, 0);\r
- if (lz == NULL) {\r
- Py_DECREF(it);\r
- return NULL;\r
- }\r
- Py_INCREF(func);\r
- lz->func = func;\r
- lz->it = it;\r
- lz->stop = 0;\r
-\r
- return (PyObject *)lz;\r
-}\r
-\r
-static void\r
-takewhile_dealloc(takewhileobject *lz)\r
-{\r
- PyObject_GC_UnTrack(lz);\r
- Py_XDECREF(lz->func);\r
- Py_XDECREF(lz->it);\r
- Py_TYPE(lz)->tp_free(lz);\r
-}\r
-\r
-static int\r
-takewhile_traverse(takewhileobject *lz, visitproc visit, void *arg)\r
-{\r
- Py_VISIT(lz->it);\r
- Py_VISIT(lz->func);\r
- return 0;\r
-}\r
-\r
-static PyObject *\r
-takewhile_next(takewhileobject *lz)\r
-{\r
- PyObject *item, *good;\r
- PyObject *it = lz->it;\r
- long ok;\r
-\r
- if (lz->stop == 1)\r
- return NULL;\r
-\r
- item = (*Py_TYPE(it)->tp_iternext)(it);\r
- if (item == NULL)\r
- return NULL;\r
-\r
- good = PyObject_CallFunctionObjArgs(lz->func, item, NULL);\r
- if (good == NULL) {\r
- Py_DECREF(item);\r
- return NULL;\r
- }\r
- ok = PyObject_IsTrue(good);\r
- Py_DECREF(good);\r
- if (ok > 0)\r
- return item;\r
- Py_DECREF(item);\r
- if (ok == 0)\r
- lz->stop = 1;\r
- return NULL;\r
-}\r
-\r
-PyDoc_STRVAR(takewhile_doc,\r
-"takewhile(predicate, iterable) --> takewhile object\n\\r
-\n\\r
-Return successive entries from an iterable as long as the \n\\r
-predicate evaluates to true for each entry.");\r
-\r
-static PyTypeObject takewhile_type = {\r
- PyVarObject_HEAD_INIT(NULL, 0)\r
- "itertools.takewhile", /* tp_name */\r
- sizeof(takewhileobject), /* tp_basicsize */\r
- 0, /* tp_itemsize */\r
- /* methods */\r
- (destructor)takewhile_dealloc, /* tp_dealloc */\r
- 0, /* tp_print */\r
- 0, /* tp_getattr */\r
- 0, /* tp_setattr */\r
- 0, /* tp_compare */\r
- 0, /* tp_repr */\r
- 0, /* tp_as_number */\r
- 0, /* tp_as_sequence */\r
- 0, /* tp_as_mapping */\r
- 0, /* tp_hash */\r
- 0, /* tp_call */\r
- 0, /* tp_str */\r
- PyObject_GenericGetAttr, /* tp_getattro */\r
- 0, /* tp_setattro */\r
- 0, /* tp_as_buffer */\r
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |\r
- Py_TPFLAGS_BASETYPE, /* tp_flags */\r
- takewhile_doc, /* tp_doc */\r
- (traverseproc)takewhile_traverse, /* tp_traverse */\r
- 0, /* tp_clear */\r
- 0, /* tp_richcompare */\r
- 0, /* tp_weaklistoffset */\r
- PyObject_SelfIter, /* tp_iter */\r
- (iternextfunc)takewhile_next, /* tp_iternext */\r
- 0, /* tp_methods */\r
- 0, /* tp_members */\r
- 0, /* tp_getset */\r
- 0, /* tp_base */\r
- 0, /* tp_dict */\r
- 0, /* tp_descr_get */\r
- 0, /* tp_descr_set */\r
- 0, /* tp_dictoffset */\r
- 0, /* tp_init */\r
- 0, /* tp_alloc */\r
- takewhile_new, /* tp_new */\r
- PyObject_GC_Del, /* tp_free */\r
-};\r
-\r
-\r
-/* islice object ************************************************************/\r
-\r
-typedef struct {\r
- PyObject_HEAD\r
- PyObject *it;\r
- Py_ssize_t next;\r
- Py_ssize_t stop;\r
- Py_ssize_t step;\r
- Py_ssize_t cnt;\r
-} isliceobject;\r
-\r
-static PyTypeObject islice_type;\r
-\r
-static PyObject *\r
-islice_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
-{\r
- PyObject *seq;\r
- Py_ssize_t start=0, stop=-1, step=1;\r
- PyObject *it, *a1=NULL, *a2=NULL, *a3=NULL;\r
- Py_ssize_t numargs;\r
- isliceobject *lz;\r
-\r
- if (type == &islice_type && !_PyArg_NoKeywords("islice()", kwds))\r
- return NULL;\r
-\r
- if (!PyArg_UnpackTuple(args, "islice", 2, 4, &seq, &a1, &a2, &a3))\r
- return NULL;\r
-\r
- numargs = PyTuple_Size(args);\r
- if (numargs == 2) {\r
- if (a1 != Py_None) {\r
- stop = PyInt_AsSsize_t(a1);\r
- if (stop == -1) {\r
- if (PyErr_Occurred())\r
- PyErr_Clear();\r
- PyErr_SetString(PyExc_ValueError,\r
- "Stop argument for islice() must be None or an integer: 0 <= x <= maxint.");\r
- return NULL;\r
- }\r
- }\r
- } else {\r
- if (a1 != Py_None)\r
- start = PyInt_AsSsize_t(a1);\r
- if (start == -1 && PyErr_Occurred())\r
- PyErr_Clear();\r
- if (a2 != Py_None) {\r
- stop = PyInt_AsSsize_t(a2);\r
- if (stop == -1) {\r
- if (PyErr_Occurred())\r
- PyErr_Clear();\r
- PyErr_SetString(PyExc_ValueError,\r
- "Stop argument for islice() must be None or an integer: 0 <= x <= maxint.");\r
- return NULL;\r
- }\r
- }\r
- }\r
- if (start<0 || stop<-1) {\r
- PyErr_SetString(PyExc_ValueError,\r
- "Indices for islice() must be None or an integer: 0 <= x <= maxint.");\r
- return NULL;\r
- }\r
-\r
- if (a3 != NULL) {\r
- if (a3 != Py_None)\r
- step = PyInt_AsSsize_t(a3);\r
- if (step == -1 && PyErr_Occurred())\r
- PyErr_Clear();\r
- }\r
- if (step<1) {\r
- PyErr_SetString(PyExc_ValueError,\r
- "Step for islice() must be a positive integer or None.");\r
- return NULL;\r
- }\r
-\r
- /* Get iterator. */\r
- it = PyObject_GetIter(seq);\r
- if (it == NULL)\r
- return NULL;\r
-\r
- /* create isliceobject structure */\r
- lz = (isliceobject *)type->tp_alloc(type, 0);\r
- if (lz == NULL) {\r
- Py_DECREF(it);\r
- return NULL;\r
- }\r
- lz->it = it;\r
- lz->next = start;\r
- lz->stop = stop;\r
- lz->step = step;\r
- lz->cnt = 0L;\r
-\r
- return (PyObject *)lz;\r
-}\r
-\r
-static void\r
-islice_dealloc(isliceobject *lz)\r
-{\r
- PyObject_GC_UnTrack(lz);\r
- Py_XDECREF(lz->it);\r
- Py_TYPE(lz)->tp_free(lz);\r
-}\r
-\r
-static int\r
-islice_traverse(isliceobject *lz, visitproc visit, void *arg)\r
-{\r
- Py_VISIT(lz->it);\r
- return 0;\r
-}\r
-\r
-static PyObject *\r
-islice_next(isliceobject *lz)\r
-{\r
- PyObject *item;\r
- PyObject *it = lz->it;\r
- Py_ssize_t stop = lz->stop;\r
- Py_ssize_t oldnext;\r
- PyObject *(*iternext)(PyObject *);\r
-\r
- if (it == NULL)\r
- return NULL;\r
-\r
- iternext = *Py_TYPE(it)->tp_iternext;\r
- while (lz->cnt < lz->next) {\r
- item = iternext(it);\r
- if (item == NULL)\r
- goto empty;\r
- Py_DECREF(item);\r
- lz->cnt++;\r
- }\r
- if (stop != -1 && lz->cnt >= stop)\r
- goto empty;\r
- item = iternext(it);\r
- if (item == NULL)\r
- goto empty;\r
- lz->cnt++;\r
- oldnext = lz->next;\r
- /* The (size_t) cast below avoids the danger of undefined\r
- behaviour from signed integer overflow. */\r
- lz->next += (size_t)lz->step;\r
- if (lz->next < oldnext || (stop != -1 && lz->next > stop))\r
- lz->next = stop;\r
- return item;\r
-\r
-empty:\r
- Py_CLEAR(lz->it);\r
- return NULL;\r
-}\r
-\r
-PyDoc_STRVAR(islice_doc,\r
-"islice(iterable, [start,] stop [, step]) --> islice object\n\\r
-\n\\r
-Return an iterator whose next() method returns selected values from an\n\\r
-iterable. If start is specified, will skip all preceding elements;\n\\r
-otherwise, start defaults to zero. Step defaults to one. If\n\\r
-specified as another value, step determines how many values are \n\\r
-skipped between successive calls. Works like a slice() on a list\n\\r
-but returns an iterator.");\r
-\r
-static PyTypeObject islice_type = {\r
- PyVarObject_HEAD_INIT(NULL, 0)\r
- "itertools.islice", /* tp_name */\r
- sizeof(isliceobject), /* tp_basicsize */\r
- 0, /* tp_itemsize */\r
- /* methods */\r
- (destructor)islice_dealloc, /* tp_dealloc */\r
- 0, /* tp_print */\r
- 0, /* tp_getattr */\r
- 0, /* tp_setattr */\r
- 0, /* tp_compare */\r
- 0, /* tp_repr */\r
- 0, /* tp_as_number */\r
- 0, /* tp_as_sequence */\r
- 0, /* tp_as_mapping */\r
- 0, /* tp_hash */\r
- 0, /* tp_call */\r
- 0, /* tp_str */\r
- PyObject_GenericGetAttr, /* tp_getattro */\r
- 0, /* tp_setattro */\r
- 0, /* tp_as_buffer */\r
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |\r
- Py_TPFLAGS_BASETYPE, /* tp_flags */\r
- islice_doc, /* tp_doc */\r
- (traverseproc)islice_traverse, /* tp_traverse */\r
- 0, /* tp_clear */\r
- 0, /* tp_richcompare */\r
- 0, /* tp_weaklistoffset */\r
- PyObject_SelfIter, /* tp_iter */\r
- (iternextfunc)islice_next, /* tp_iternext */\r
- 0, /* tp_methods */\r
- 0, /* tp_members */\r
- 0, /* tp_getset */\r
- 0, /* tp_base */\r
- 0, /* tp_dict */\r
- 0, /* tp_descr_get */\r
- 0, /* tp_descr_set */\r
- 0, /* tp_dictoffset */\r
- 0, /* tp_init */\r
- 0, /* tp_alloc */\r
- islice_new, /* tp_new */\r
- PyObject_GC_Del, /* tp_free */\r
-};\r
-\r
-\r
-/* starmap object ************************************************************/\r
-\r
-typedef struct {\r
- PyObject_HEAD\r
- PyObject *func;\r
- PyObject *it;\r
-} starmapobject;\r
-\r
-static PyTypeObject starmap_type;\r
-\r
-static PyObject *\r
-starmap_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
-{\r
- PyObject *func, *seq;\r
- PyObject *it;\r
- starmapobject *lz;\r
-\r
- if (type == &starmap_type && !_PyArg_NoKeywords("starmap()", kwds))\r
- return NULL;\r
-\r
- if (!PyArg_UnpackTuple(args, "starmap", 2, 2, &func, &seq))\r
- return NULL;\r
-\r
- /* Get iterator. */\r
- it = PyObject_GetIter(seq);\r
- if (it == NULL)\r
- return NULL;\r
-\r
- /* create starmapobject structure */\r
- lz = (starmapobject *)type->tp_alloc(type, 0);\r
- if (lz == NULL) {\r
- Py_DECREF(it);\r
- return NULL;\r
- }\r
- Py_INCREF(func);\r
- lz->func = func;\r
- lz->it = it;\r
-\r
- return (PyObject *)lz;\r
-}\r
-\r
-static void\r
-starmap_dealloc(starmapobject *lz)\r
-{\r
- PyObject_GC_UnTrack(lz);\r
- Py_XDECREF(lz->func);\r
- Py_XDECREF(lz->it);\r
- Py_TYPE(lz)->tp_free(lz);\r
-}\r
-\r
-static int\r
-starmap_traverse(starmapobject *lz, visitproc visit, void *arg)\r
-{\r
- Py_VISIT(lz->it);\r
- Py_VISIT(lz->func);\r
- return 0;\r
-}\r
-\r
-static PyObject *\r
-starmap_next(starmapobject *lz)\r
-{\r
- PyObject *args;\r
- PyObject *result;\r
- PyObject *it = lz->it;\r
-\r
- args = (*Py_TYPE(it)->tp_iternext)(it);\r
- if (args == NULL)\r
- return NULL;\r
- if (!PyTuple_CheckExact(args)) {\r
- PyObject *newargs = PySequence_Tuple(args);\r
- Py_DECREF(args);\r
- if (newargs == NULL)\r
- return NULL;\r
- args = newargs;\r
- }\r
- result = PyObject_Call(lz->func, args, NULL);\r
- Py_DECREF(args);\r
- return result;\r
-}\r
-\r
-PyDoc_STRVAR(starmap_doc,\r
-"starmap(function, sequence) --> starmap object\n\\r
-\n\\r
-Return an iterator whose values are returned from the function evaluated\n\\r
-with a argument tuple taken from the given sequence.");\r
-\r
-static PyTypeObject starmap_type = {\r
- PyVarObject_HEAD_INIT(NULL, 0)\r
- "itertools.starmap", /* tp_name */\r
- sizeof(starmapobject), /* tp_basicsize */\r
- 0, /* tp_itemsize */\r
- /* methods */\r
- (destructor)starmap_dealloc, /* tp_dealloc */\r
- 0, /* tp_print */\r
- 0, /* tp_getattr */\r
- 0, /* tp_setattr */\r
- 0, /* tp_compare */\r
- 0, /* tp_repr */\r
- 0, /* tp_as_number */\r
- 0, /* tp_as_sequence */\r
- 0, /* tp_as_mapping */\r
- 0, /* tp_hash */\r
- 0, /* tp_call */\r
- 0, /* tp_str */\r
- PyObject_GenericGetAttr, /* tp_getattro */\r
- 0, /* tp_setattro */\r
- 0, /* tp_as_buffer */\r
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |\r
- Py_TPFLAGS_BASETYPE, /* tp_flags */\r
- starmap_doc, /* tp_doc */\r
- (traverseproc)starmap_traverse, /* tp_traverse */\r
- 0, /* tp_clear */\r
- 0, /* tp_richcompare */\r
- 0, /* tp_weaklistoffset */\r
- PyObject_SelfIter, /* tp_iter */\r
- (iternextfunc)starmap_next, /* tp_iternext */\r
- 0, /* tp_methods */\r
- 0, /* tp_members */\r
- 0, /* tp_getset */\r
- 0, /* tp_base */\r
- 0, /* tp_dict */\r
- 0, /* tp_descr_get */\r
- 0, /* tp_descr_set */\r
- 0, /* tp_dictoffset */\r
- 0, /* tp_init */\r
- 0, /* tp_alloc */\r
- starmap_new, /* tp_new */\r
- PyObject_GC_Del, /* tp_free */\r
-};\r
-\r
-\r
-/* imap object ************************************************************/\r
-\r
-typedef struct {\r
- PyObject_HEAD\r
- PyObject *iters;\r
- PyObject *func;\r
-} imapobject;\r
-\r
-static PyTypeObject imap_type;\r
-\r
-static PyObject *\r
-imap_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
-{\r
- PyObject *it, *iters, *func;\r
- imapobject *lz;\r
- Py_ssize_t numargs, i;\r
-\r
- if (type == &imap_type && !_PyArg_NoKeywords("imap()", kwds))\r
- return NULL;\r
-\r
- numargs = PyTuple_Size(args);\r
- if (numargs < 2) {\r
- PyErr_SetString(PyExc_TypeError,\r
- "imap() must have at least two arguments.");\r
- return NULL;\r
- }\r
-\r
- iters = PyTuple_New(numargs-1);\r
- if (iters == NULL)\r
- return NULL;\r
-\r
- for (i=1 ; i<numargs ; i++) {\r
- /* Get iterator. */\r
- it = PyObject_GetIter(PyTuple_GET_ITEM(args, i));\r
- if (it == NULL) {\r
- Py_DECREF(iters);\r
- return NULL;\r
- }\r
- PyTuple_SET_ITEM(iters, i-1, it);\r
- }\r
-\r
- /* create imapobject structure */\r
- lz = (imapobject *)type->tp_alloc(type, 0);\r
- if (lz == NULL) {\r
- Py_DECREF(iters);\r
- return NULL;\r
- }\r
- lz->iters = iters;\r
- func = PyTuple_GET_ITEM(args, 0);\r
- Py_INCREF(func);\r
- lz->func = func;\r
-\r
- return (PyObject *)lz;\r
-}\r
-\r
-static void\r
-imap_dealloc(imapobject *lz)\r
-{\r
- PyObject_GC_UnTrack(lz);\r
- Py_XDECREF(lz->iters);\r
- Py_XDECREF(lz->func);\r
- Py_TYPE(lz)->tp_free(lz);\r
-}\r
-\r
-static int\r
-imap_traverse(imapobject *lz, visitproc visit, void *arg)\r
-{\r
- Py_VISIT(lz->iters);\r
- Py_VISIT(lz->func);\r
- return 0;\r
-}\r
-\r
-/*\r
-imap() is an iterator version of __builtins__.map() except that it does\r
-not have the None fill-in feature. That was intentionally left out for\r
-the following reasons:\r
-\r
- 1) Itertools are designed to be easily combined and chained together.\r
- Having all tools stop with the shortest input is a unifying principle\r
- that makes it easier to combine finite iterators (supplying data) with\r
- infinite iterators like count() and repeat() (for supplying sequential\r
- or constant arguments to a function).\r
-\r
- 2) In typical use cases for combining itertools, having one finite data\r
- supplier run out before another is likely to be an error condition which\r
- should not pass silently by automatically supplying None.\r
-\r
- 3) The use cases for automatic None fill-in are rare -- not many functions\r
- do something useful when a parameter suddenly switches type and becomes\r
- None.\r
-\r
- 4) If a need does arise, it can be met by __builtins__.map() or by\r
- writing: chain(iterable, repeat(None)).\r
-\r
- 5) Similar toolsets in Haskell and SML do not have automatic None fill-in.\r
-*/\r
-\r
-static PyObject *\r
-imap_next(imapobject *lz)\r
-{\r
- PyObject *val;\r
- PyObject *argtuple;\r
- PyObject *result;\r
- Py_ssize_t numargs, i;\r
-\r
- numargs = PyTuple_Size(lz->iters);\r
- argtuple = PyTuple_New(numargs);\r
- if (argtuple == NULL)\r
- return NULL;\r
-\r
- for (i=0 ; i<numargs ; i++) {\r
- val = PyIter_Next(PyTuple_GET_ITEM(lz->iters, i));\r
- if (val == NULL) {\r
- Py_DECREF(argtuple);\r
- return NULL;\r
- }\r
- PyTuple_SET_ITEM(argtuple, i, val);\r
- }\r
- if (lz->func == Py_None)\r
- return argtuple;\r
- result = PyObject_Call(lz->func, argtuple, NULL);\r
- Py_DECREF(argtuple);\r
- return result;\r
-}\r
-\r
-PyDoc_STRVAR(imap_doc,\r
-"imap(func, *iterables) --> imap object\n\\r
-\n\\r
-Make an iterator that computes the function using arguments from\n\\r
-each of the iterables. Like map() except that it returns\n\\r
-an iterator instead of a list and that it stops when the shortest\n\\r
-iterable is exhausted instead of filling in None for shorter\n\\r
-iterables.");\r
-\r
-static PyTypeObject imap_type = {\r
- PyVarObject_HEAD_INIT(NULL, 0)\r
- "itertools.imap", /* tp_name */\r
- sizeof(imapobject), /* tp_basicsize */\r
- 0, /* tp_itemsize */\r
- /* methods */\r
- (destructor)imap_dealloc, /* tp_dealloc */\r
- 0, /* tp_print */\r
- 0, /* tp_getattr */\r
- 0, /* tp_setattr */\r
- 0, /* tp_compare */\r
- 0, /* tp_repr */\r
- 0, /* tp_as_number */\r
- 0, /* tp_as_sequence */\r
- 0, /* tp_as_mapping */\r
- 0, /* tp_hash */\r
- 0, /* tp_call */\r
- 0, /* tp_str */\r
- PyObject_GenericGetAttr, /* tp_getattro */\r
- 0, /* tp_setattro */\r
- 0, /* tp_as_buffer */\r
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |\r
- Py_TPFLAGS_BASETYPE, /* tp_flags */\r
- imap_doc, /* tp_doc */\r
- (traverseproc)imap_traverse, /* tp_traverse */\r
- 0, /* tp_clear */\r
- 0, /* tp_richcompare */\r
- 0, /* tp_weaklistoffset */\r
- PyObject_SelfIter, /* tp_iter */\r
- (iternextfunc)imap_next, /* tp_iternext */\r
- 0, /* tp_methods */\r
- 0, /* tp_members */\r
- 0, /* tp_getset */\r
- 0, /* tp_base */\r
- 0, /* tp_dict */\r
- 0, /* tp_descr_get */\r
- 0, /* tp_descr_set */\r
- 0, /* tp_dictoffset */\r
- 0, /* tp_init */\r
- 0, /* tp_alloc */\r
- imap_new, /* tp_new */\r
- PyObject_GC_Del, /* tp_free */\r
-};\r
-\r
-\r
-/* chain object ************************************************************/\r
-\r
-typedef struct {\r
- PyObject_HEAD\r
- PyObject *source; /* Iterator over input iterables */\r
- PyObject *active; /* Currently running input iterator */\r
-} chainobject;\r
-\r
-static PyTypeObject chain_type;\r
-\r
-static PyObject *\r
-chain_new_internal(PyTypeObject *type, PyObject *source)\r
-{\r
- chainobject *lz;\r
-\r
- lz = (chainobject *)type->tp_alloc(type, 0);\r
- if (lz == NULL) {\r
- Py_DECREF(source);\r
- return NULL;\r
- }\r
-\r
- lz->source = source;\r
- lz->active = NULL;\r
- return (PyObject *)lz;\r
-}\r
-\r
-static PyObject *\r
-chain_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
-{\r
- PyObject *source;\r
-\r
- if (type == &chain_type && !_PyArg_NoKeywords("chain()", kwds))\r
- return NULL;\r
-\r
- source = PyObject_GetIter(args);\r
- if (source == NULL)\r
- return NULL;\r
-\r
- return chain_new_internal(type, source);\r
-}\r
-\r
-static PyObject *\r
-chain_new_from_iterable(PyTypeObject *type, PyObject *arg)\r
-{\r
- PyObject *source;\r
-\r
- source = PyObject_GetIter(arg);\r
- if (source == NULL)\r
- return NULL;\r
-\r
- return chain_new_internal(type, source);\r
-}\r
-\r
-static void\r
-chain_dealloc(chainobject *lz)\r
-{\r
- PyObject_GC_UnTrack(lz);\r
- Py_XDECREF(lz->active);\r
- Py_XDECREF(lz->source);\r
- Py_TYPE(lz)->tp_free(lz);\r
-}\r
-\r
-static int\r
-chain_traverse(chainobject *lz, visitproc visit, void *arg)\r
-{\r
- Py_VISIT(lz->source);\r
- Py_VISIT(lz->active);\r
- return 0;\r
-}\r
-\r
-static PyObject *\r
-chain_next(chainobject *lz)\r
-{\r
- PyObject *item;\r
-\r
- if (lz->source == NULL)\r
- return NULL; /* already stopped */\r
-\r
- if (lz->active == NULL) {\r
- PyObject *iterable = PyIter_Next(lz->source);\r
- if (iterable == NULL) {\r
- Py_CLEAR(lz->source);\r
- return NULL; /* no more input sources */\r
- }\r
- lz->active = PyObject_GetIter(iterable);\r
- Py_DECREF(iterable);\r
- if (lz->active == NULL) {\r
- Py_CLEAR(lz->source);\r
- return NULL; /* input not iterable */\r
- }\r
- }\r
- item = PyIter_Next(lz->active);\r
- if (item != NULL)\r
- return item;\r
- if (PyErr_Occurred()) {\r
- if (PyErr_ExceptionMatches(PyExc_StopIteration))\r
- PyErr_Clear();\r
- else\r
- return NULL; /* input raised an exception */\r
- }\r
- Py_CLEAR(lz->active);\r
- return chain_next(lz); /* recurse and use next active */\r
-}\r
-\r
-PyDoc_STRVAR(chain_doc,\r
-"chain(*iterables) --> chain object\n\\r
-\n\\r
-Return a chain object whose .next() method returns elements from the\n\\r
-first iterable until it is exhausted, then elements from the next\n\\r
-iterable, until all of the iterables are exhausted.");\r
-\r
-PyDoc_STRVAR(chain_from_iterable_doc,\r
-"chain.from_iterable(iterable) --> chain object\n\\r
-\n\\r
-Alternate chain() contructor taking a single iterable argument\n\\r
-that evaluates lazily.");\r
-\r
-static PyMethodDef chain_methods[] = {\r
- {"from_iterable", (PyCFunction) chain_new_from_iterable, METH_O | METH_CLASS,\r
- chain_from_iterable_doc},\r
- {NULL, NULL} /* sentinel */\r
-};\r
-\r
-static PyTypeObject chain_type = {\r
- PyVarObject_HEAD_INIT(NULL, 0)\r
- "itertools.chain", /* tp_name */\r
- sizeof(chainobject), /* tp_basicsize */\r
- 0, /* tp_itemsize */\r
- /* methods */\r
- (destructor)chain_dealloc, /* tp_dealloc */\r
- 0, /* tp_print */\r
- 0, /* tp_getattr */\r
- 0, /* tp_setattr */\r
- 0, /* tp_compare */\r
- 0, /* tp_repr */\r
- 0, /* tp_as_number */\r
- 0, /* tp_as_sequence */\r
- 0, /* tp_as_mapping */\r
- 0, /* tp_hash */\r
- 0, /* tp_call */\r
- 0, /* tp_str */\r
- PyObject_GenericGetAttr, /* tp_getattro */\r
- 0, /* tp_setattro */\r
- 0, /* tp_as_buffer */\r
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |\r
- Py_TPFLAGS_BASETYPE, /* tp_flags */\r
- chain_doc, /* tp_doc */\r
- (traverseproc)chain_traverse, /* tp_traverse */\r
- 0, /* tp_clear */\r
- 0, /* tp_richcompare */\r
- 0, /* tp_weaklistoffset */\r
- PyObject_SelfIter, /* tp_iter */\r
- (iternextfunc)chain_next, /* tp_iternext */\r
- chain_methods, /* tp_methods */\r
- 0, /* tp_members */\r
- 0, /* tp_getset */\r
- 0, /* tp_base */\r
- 0, /* tp_dict */\r
- 0, /* tp_descr_get */\r
- 0, /* tp_descr_set */\r
- 0, /* tp_dictoffset */\r
- 0, /* tp_init */\r
- 0, /* tp_alloc */\r
- chain_new, /* tp_new */\r
- PyObject_GC_Del, /* tp_free */\r
-};\r
-\r
-\r
-/* product object ************************************************************/\r
-\r
-typedef struct {\r
- PyObject_HEAD\r
- PyObject *pools; /* tuple of pool tuples */\r
- Py_ssize_t *indices; /* one index per pool */\r
- PyObject *result; /* most recently returned result tuple */\r
- int stopped; /* set to 1 when the product iterator is exhausted */\r
-} productobject;\r
-\r
-static PyTypeObject product_type;\r
-\r
-static PyObject *\r
-product_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
-{\r
- productobject *lz;\r
- Py_ssize_t nargs, npools, repeat=1;\r
- PyObject *pools = NULL;\r
- Py_ssize_t *indices = NULL;\r
- Py_ssize_t i;\r
-\r
- if (kwds != NULL) {\r
- char *kwlist[] = {"repeat", 0};\r
- PyObject *tmpargs = PyTuple_New(0);\r
- if (tmpargs == NULL)\r
- return NULL;\r
- if (!PyArg_ParseTupleAndKeywords(tmpargs, kwds, "|n:product", kwlist, &repeat)) {\r
- Py_DECREF(tmpargs);\r
- return NULL;\r
- }\r
- Py_DECREF(tmpargs);\r
- if (repeat < 0) {\r
- PyErr_SetString(PyExc_ValueError,\r
- "repeat argument cannot be negative");\r
- return NULL;\r
- }\r
- }\r
-\r
- assert(PyTuple_CheckExact(args));\r
- if (repeat == 0) {\r
- nargs = 0;\r
- } else {\r
- nargs = PyTuple_GET_SIZE(args);\r
- if ((size_t)nargs > PY_SSIZE_T_MAX/sizeof(Py_ssize_t)/repeat) {\r
- PyErr_SetString(PyExc_OverflowError, "repeat argument too large");\r
- return NULL;\r
- }\r
- }\r
- npools = nargs * repeat;\r
-\r
- indices = PyMem_New(Py_ssize_t, npools);\r
- if (indices == NULL) {\r
- PyErr_NoMemory();\r
- goto error;\r
- }\r
-\r
- pools = PyTuple_New(npools);\r
- if (pools == NULL)\r
- goto error;\r
-\r
- for (i=0; i < nargs ; ++i) {\r
- PyObject *item = PyTuple_GET_ITEM(args, i);\r
- PyObject *pool = PySequence_Tuple(item);\r
- if (pool == NULL)\r
- goto error;\r
- PyTuple_SET_ITEM(pools, i, pool);\r
- indices[i] = 0;\r
- }\r
- for ( ; i < npools; ++i) {\r
- PyObject *pool = PyTuple_GET_ITEM(pools, i - nargs);\r
- Py_INCREF(pool);\r
- PyTuple_SET_ITEM(pools, i, pool);\r
- indices[i] = 0;\r
- }\r
-\r
- /* create productobject structure */\r
- lz = (productobject *)type->tp_alloc(type, 0);\r
- if (lz == NULL)\r
- goto error;\r
-\r
- lz->pools = pools;\r
- lz->indices = indices;\r
- lz->result = NULL;\r
- lz->stopped = 0;\r
-\r
- return (PyObject *)lz;\r
-\r
-error:\r
- if (indices != NULL)\r
- PyMem_Free(indices);\r
- Py_XDECREF(pools);\r
- return NULL;\r
-}\r
-\r
-static void\r
-product_dealloc(productobject *lz)\r
-{\r
- PyObject_GC_UnTrack(lz);\r
- Py_XDECREF(lz->pools);\r
- Py_XDECREF(lz->result);\r
- if (lz->indices != NULL)\r
- PyMem_Free(lz->indices);\r
- Py_TYPE(lz)->tp_free(lz);\r
-}\r
-\r
-static int\r
-product_traverse(productobject *lz, visitproc visit, void *arg)\r
-{\r
- Py_VISIT(lz->pools);\r
- Py_VISIT(lz->result);\r
- return 0;\r
-}\r
-\r
-static PyObject *\r
-product_next(productobject *lz)\r
-{\r
- PyObject *pool;\r
- PyObject *elem;\r
- PyObject *oldelem;\r
- PyObject *pools = lz->pools;\r
- PyObject *result = lz->result;\r
- Py_ssize_t npools = PyTuple_GET_SIZE(pools);\r
- Py_ssize_t i;\r
-\r
- if (lz->stopped)\r
- return NULL;\r
-\r
- if (result == NULL) {\r
- /* On the first pass, return an initial tuple filled with the\r
- first element from each pool. */\r
- result = PyTuple_New(npools);\r
- if (result == NULL)\r
- goto empty;\r
- lz->result = result;\r
- for (i=0; i < npools; i++) {\r
- pool = PyTuple_GET_ITEM(pools, i);\r
- if (PyTuple_GET_SIZE(pool) == 0)\r
- goto empty;\r
- elem = PyTuple_GET_ITEM(pool, 0);\r
- Py_INCREF(elem);\r
- PyTuple_SET_ITEM(result, i, elem);\r
- }\r
- } else {\r
- Py_ssize_t *indices = lz->indices;\r
-\r
- /* Copy the previous result tuple or re-use it if available */\r
- if (Py_REFCNT(result) > 1) {\r
- PyObject *old_result = result;\r
- result = PyTuple_New(npools);\r
- if (result == NULL)\r
- goto empty;\r
- lz->result = result;\r
- for (i=0; i < npools; i++) {\r
- elem = PyTuple_GET_ITEM(old_result, i);\r
- Py_INCREF(elem);\r
- PyTuple_SET_ITEM(result, i, elem);\r
- }\r
- Py_DECREF(old_result);\r
- }\r
- /* Now, we've got the only copy so we can update it in-place */\r
- assert (npools==0 || Py_REFCNT(result) == 1);\r
-\r
- /* Update the pool indices right-to-left. Only advance to the\r
- next pool when the previous one rolls-over */\r
- for (i=npools-1 ; i >= 0 ; i--) {\r
- pool = PyTuple_GET_ITEM(pools, i);\r
- indices[i]++;\r
- if (indices[i] == PyTuple_GET_SIZE(pool)) {\r
- /* Roll-over and advance to next pool */\r
- indices[i] = 0;\r
- elem = PyTuple_GET_ITEM(pool, 0);\r
- Py_INCREF(elem);\r
- oldelem = PyTuple_GET_ITEM(result, i);\r
- PyTuple_SET_ITEM(result, i, elem);\r
- Py_DECREF(oldelem);\r
- } else {\r
- /* No rollover. Just increment and stop here. */\r
- elem = PyTuple_GET_ITEM(pool, indices[i]);\r
- Py_INCREF(elem);\r
- oldelem = PyTuple_GET_ITEM(result, i);\r
- PyTuple_SET_ITEM(result, i, elem);\r
- Py_DECREF(oldelem);\r
- break;\r
- }\r
- }\r
-\r
- /* If i is negative, then the indices have all rolled-over\r
- and we're done. */\r
- if (i < 0)\r
- goto empty;\r
- }\r
-\r
- Py_INCREF(result);\r
- return result;\r
-\r
-empty:\r
- lz->stopped = 1;\r
- return NULL;\r
-}\r
-\r
-PyDoc_STRVAR(product_doc,\r
-"product(*iterables) --> product object\n\\r
-\n\\r
-Cartesian product of input iterables. Equivalent to nested for-loops.\n\n\\r
-For example, product(A, B) returns the same as: ((x,y) for x in A for y in B).\n\\r
-The leftmost iterators are in the outermost for-loop, so the output tuples\n\\r
-cycle in a manner similar to an odometer (with the rightmost element changing\n\\r
-on every iteration).\n\n\\r
-To compute the product of an iterable with itself, specify the number\n\\r
-of repetitions with the optional repeat keyword argument. For example,\n\\r
-product(A, repeat=4) means the same as product(A, A, A, A).\n\n\\r
-product('ab', range(3)) --> ('a',0) ('a',1) ('a',2) ('b',0) ('b',1) ('b',2)\n\\r
-product((0,1), (0,1), (0,1)) --> (0,0,0) (0,0,1) (0,1,0) (0,1,1) (1,0,0) ...");\r
-\r
-static PyTypeObject product_type = {\r
- PyVarObject_HEAD_INIT(NULL, 0)\r
- "itertools.product", /* tp_name */\r
- sizeof(productobject), /* tp_basicsize */\r
- 0, /* tp_itemsize */\r
- /* methods */\r
- (destructor)product_dealloc, /* tp_dealloc */\r
- 0, /* tp_print */\r
- 0, /* tp_getattr */\r
- 0, /* tp_setattr */\r
- 0, /* tp_compare */\r
- 0, /* tp_repr */\r
- 0, /* tp_as_number */\r
- 0, /* tp_as_sequence */\r
- 0, /* tp_as_mapping */\r
- 0, /* tp_hash */\r
- 0, /* tp_call */\r
- 0, /* tp_str */\r
- PyObject_GenericGetAttr, /* tp_getattro */\r
- 0, /* tp_setattro */\r
- 0, /* tp_as_buffer */\r
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |\r
- Py_TPFLAGS_BASETYPE, /* tp_flags */\r
- product_doc, /* tp_doc */\r
- (traverseproc)product_traverse, /* tp_traverse */\r
- 0, /* tp_clear */\r
- 0, /* tp_richcompare */\r
- 0, /* tp_weaklistoffset */\r
- PyObject_SelfIter, /* tp_iter */\r
- (iternextfunc)product_next, /* tp_iternext */\r
- 0, /* tp_methods */\r
- 0, /* tp_members */\r
- 0, /* tp_getset */\r
- 0, /* tp_base */\r
- 0, /* tp_dict */\r
- 0, /* tp_descr_get */\r
- 0, /* tp_descr_set */\r
- 0, /* tp_dictoffset */\r
- 0, /* tp_init */\r
- 0, /* tp_alloc */\r
- product_new, /* tp_new */\r
- PyObject_GC_Del, /* tp_free */\r
-};\r
-\r
-\r
-/* combinations object ************************************************************/\r
-\r
-typedef struct {\r
- PyObject_HEAD\r
- PyObject *pool; /* input converted to a tuple */\r
- Py_ssize_t *indices; /* one index per result element */\r
- PyObject *result; /* most recently returned result tuple */\r
- Py_ssize_t r; /* size of result tuple */\r
- int stopped; /* set to 1 when the combinations iterator is exhausted */\r
-} combinationsobject;\r
-\r
-static PyTypeObject combinations_type;\r
-\r
-static PyObject *\r
-combinations_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
-{\r
- combinationsobject *co;\r
- Py_ssize_t n;\r
- Py_ssize_t r;\r
- PyObject *pool = NULL;\r
- PyObject *iterable = NULL;\r
- Py_ssize_t *indices = NULL;\r
- Py_ssize_t i;\r
- static char *kwargs[] = {"iterable", "r", NULL};\r
-\r
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "On:combinations", kwargs,\r
- &iterable, &r))\r
- return NULL;\r
-\r
- pool = PySequence_Tuple(iterable);\r
- if (pool == NULL)\r
- goto error;\r
- n = PyTuple_GET_SIZE(pool);\r
- if (r < 0) {\r
- PyErr_SetString(PyExc_ValueError, "r must be non-negative");\r
- goto error;\r
- }\r
-\r
- indices = PyMem_New(Py_ssize_t, r);\r
- if (indices == NULL) {\r
- PyErr_NoMemory();\r
- goto error;\r
- }\r
-\r
- for (i=0 ; i<r ; i++)\r
- indices[i] = i;\r
-\r
- /* create combinationsobject structure */\r
- co = (combinationsobject *)type->tp_alloc(type, 0);\r
- if (co == NULL)\r
- goto error;\r
-\r
- co->pool = pool;\r
- co->indices = indices;\r
- co->result = NULL;\r
- co->r = r;\r
- co->stopped = r > n ? 1 : 0;\r
-\r
- return (PyObject *)co;\r
-\r
-error:\r
- if (indices != NULL)\r
- PyMem_Free(indices);\r
- Py_XDECREF(pool);\r
- return NULL;\r
-}\r
-\r
-static void\r
-combinations_dealloc(combinationsobject *co)\r
-{\r
- PyObject_GC_UnTrack(co);\r
- Py_XDECREF(co->pool);\r
- Py_XDECREF(co->result);\r
- if (co->indices != NULL)\r
- PyMem_Free(co->indices);\r
- Py_TYPE(co)->tp_free(co);\r
-}\r
-\r
-static int\r
-combinations_traverse(combinationsobject *co, visitproc visit, void *arg)\r
-{\r
- Py_VISIT(co->pool);\r
- Py_VISIT(co->result);\r
- return 0;\r
-}\r
-\r
-static PyObject *\r
-combinations_next(combinationsobject *co)\r
-{\r
- PyObject *elem;\r
- PyObject *oldelem;\r
- PyObject *pool = co->pool;\r
- Py_ssize_t *indices = co->indices;\r
- PyObject *result = co->result;\r
- Py_ssize_t n = PyTuple_GET_SIZE(pool);\r
- Py_ssize_t r = co->r;\r
- Py_ssize_t i, j, index;\r
-\r
- if (co->stopped)\r
- return NULL;\r
-\r
- if (result == NULL) {\r
- /* On the first pass, initialize result tuple using the indices */\r
- result = PyTuple_New(r);\r
- if (result == NULL)\r
- goto empty;\r
- co->result = result;\r
- for (i=0; i<r ; i++) {\r
- index = indices[i];\r
- elem = PyTuple_GET_ITEM(pool, index);\r
- Py_INCREF(elem);\r
- PyTuple_SET_ITEM(result, i, elem);\r
- }\r
- } else {\r
- /* Copy the previous result tuple or re-use it if available */\r
- if (Py_REFCNT(result) > 1) {\r
- PyObject *old_result = result;\r
- result = PyTuple_New(r);\r
- if (result == NULL)\r
- goto empty;\r
- co->result = result;\r
- for (i=0; i<r ; i++) {\r
- elem = PyTuple_GET_ITEM(old_result, i);\r
- Py_INCREF(elem);\r
- PyTuple_SET_ITEM(result, i, elem);\r
- }\r
- Py_DECREF(old_result);\r
- }\r
- /* Now, we've got the only copy so we can update it in-place\r
- * CPython's empty tuple is a singleton and cached in\r
- * PyTuple's freelist.\r
- */\r
- assert(r == 0 || Py_REFCNT(result) == 1);\r
-\r
- /* Scan indices right-to-left until finding one that is not\r
- at its maximum (i + n - r). */\r
- for (i=r-1 ; i >= 0 && indices[i] == i+n-r ; i--)\r
- ;\r
-\r
- /* If i is negative, then the indices are all at\r
- their maximum value and we're done. */\r
- if (i < 0)\r
- goto empty;\r
-\r
- /* Increment the current index which we know is not at its\r
- maximum. Then move back to the right setting each index\r
- to its lowest possible value (one higher than the index\r
- to its left -- this maintains the sort order invariant). */\r
- indices[i]++;\r
- for (j=i+1 ; j<r ; j++)\r
- indices[j] = indices[j-1] + 1;\r
-\r
- /* Update the result tuple for the new indices\r
- starting with i, the leftmost index that changed */\r
- for ( ; i<r ; i++) {\r
- index = indices[i];\r
- elem = PyTuple_GET_ITEM(pool, index);\r
- Py_INCREF(elem);\r
- oldelem = PyTuple_GET_ITEM(result, i);\r
- PyTuple_SET_ITEM(result, i, elem);\r
- Py_DECREF(oldelem);\r
- }\r
- }\r
-\r
- Py_INCREF(result);\r
- return result;\r
-\r
-empty:\r
- co->stopped = 1;\r
- return NULL;\r
-}\r
-\r
-PyDoc_STRVAR(combinations_doc,\r
-"combinations(iterable, r) --> combinations object\n\\r
-\n\\r
-Return successive r-length combinations of elements in the iterable.\n\n\\r
-combinations(range(4), 3) --> (0,1,2), (0,1,3), (0,2,3), (1,2,3)");\r
-\r
-static PyTypeObject combinations_type = {\r
- PyVarObject_HEAD_INIT(NULL, 0)\r
- "itertools.combinations", /* tp_name */\r
- sizeof(combinationsobject), /* tp_basicsize */\r
- 0, /* tp_itemsize */\r
- /* methods */\r
- (destructor)combinations_dealloc, /* tp_dealloc */\r
- 0, /* tp_print */\r
- 0, /* tp_getattr */\r
- 0, /* tp_setattr */\r
- 0, /* tp_compare */\r
- 0, /* tp_repr */\r
- 0, /* tp_as_number */\r
- 0, /* tp_as_sequence */\r
- 0, /* tp_as_mapping */\r
- 0, /* tp_hash */\r
- 0, /* tp_call */\r
- 0, /* tp_str */\r
- PyObject_GenericGetAttr, /* tp_getattro */\r
- 0, /* tp_setattro */\r
- 0, /* tp_as_buffer */\r
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |\r
- Py_TPFLAGS_BASETYPE, /* tp_flags */\r
- combinations_doc, /* tp_doc */\r
- (traverseproc)combinations_traverse, /* tp_traverse */\r
- 0, /* tp_clear */\r
- 0, /* tp_richcompare */\r
- 0, /* tp_weaklistoffset */\r
- PyObject_SelfIter, /* tp_iter */\r
- (iternextfunc)combinations_next, /* tp_iternext */\r
- 0, /* tp_methods */\r
- 0, /* tp_members */\r
- 0, /* tp_getset */\r
- 0, /* tp_base */\r
- 0, /* tp_dict */\r
- 0, /* tp_descr_get */\r
- 0, /* tp_descr_set */\r
- 0, /* tp_dictoffset */\r
- 0, /* tp_init */\r
- 0, /* tp_alloc */\r
- combinations_new, /* tp_new */\r
- PyObject_GC_Del, /* tp_free */\r
-};\r
-\r
-\r
-/* combinations with replacement object *******************************************/\r
-\r
-/* Equivalent to:\r
-\r
- def combinations_with_replacement(iterable, r):\r
- "combinations_with_replacement('ABC', 2) --> AA AB AC BB BC CC"\r
- # number items returned: (n+r-1)! / r! / (n-1)!\r
- pool = tuple(iterable)\r
- n = len(pool)\r
- indices = [0] * r\r
- yield tuple(pool[i] for i in indices)\r
- while 1:\r
- for i in reversed(range(r)):\r
- if indices[i] != n - 1:\r
- break\r
- else:\r
- return\r
- indices[i:] = [indices[i] + 1] * (r - i)\r
- yield tuple(pool[i] for i in indices)\r
-\r
- def combinations_with_replacement2(iterable, r):\r
- 'Alternate version that filters from product()'\r
- pool = tuple(iterable)\r
- n = len(pool)\r
- for indices in product(range(n), repeat=r):\r
- if sorted(indices) == list(indices):\r
- yield tuple(pool[i] for i in indices)\r
-*/\r
-typedef struct {\r
- PyObject_HEAD\r
- PyObject *pool; /* input converted to a tuple */\r
- Py_ssize_t *indices; /* one index per result element */\r
- PyObject *result; /* most recently returned result tuple */\r
- Py_ssize_t r; /* size of result tuple */\r
- int stopped; /* set to 1 when the cwr iterator is exhausted */\r
-} cwrobject;\r
-\r
-static PyTypeObject cwr_type;\r
-\r
-static PyObject *\r
-cwr_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
-{\r
- cwrobject *co;\r
- Py_ssize_t n;\r
- Py_ssize_t r;\r
- PyObject *pool = NULL;\r
- PyObject *iterable = NULL;\r
- Py_ssize_t *indices = NULL;\r
- Py_ssize_t i;\r
- static char *kwargs[] = {"iterable", "r", NULL};\r
-\r
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "On:combinations_with_replacement", kwargs,\r
- &iterable, &r))\r
- return NULL;\r
-\r
- pool = PySequence_Tuple(iterable);\r
- if (pool == NULL)\r
- goto error;\r
- n = PyTuple_GET_SIZE(pool);\r
- if (r < 0) {\r
- PyErr_SetString(PyExc_ValueError, "r must be non-negative");\r
- goto error;\r
- }\r
-\r
- indices = PyMem_New(Py_ssize_t, r);\r
- if (indices == NULL) {\r
- PyErr_NoMemory();\r
- goto error;\r
- }\r
-\r
- for (i=0 ; i<r ; i++)\r
- indices[i] = 0;\r
-\r
- /* create cwrobject structure */\r
- co = (cwrobject *)type->tp_alloc(type, 0);\r
- if (co == NULL)\r
- goto error;\r
-\r
- co->pool = pool;\r
- co->indices = indices;\r
- co->result = NULL;\r
- co->r = r;\r
- co->stopped = !n && r;\r
-\r
- return (PyObject *)co;\r
-\r
-error:\r
- if (indices != NULL)\r
- PyMem_Free(indices);\r
- Py_XDECREF(pool);\r
- return NULL;\r
-}\r
-\r
-static void\r
-cwr_dealloc(cwrobject *co)\r
-{\r
- PyObject_GC_UnTrack(co);\r
- Py_XDECREF(co->pool);\r
- Py_XDECREF(co->result);\r
- if (co->indices != NULL)\r
- PyMem_Free(co->indices);\r
- Py_TYPE(co)->tp_free(co);\r
-}\r
-\r
-static int\r
-cwr_traverse(cwrobject *co, visitproc visit, void *arg)\r
-{\r
- Py_VISIT(co->pool);\r
- Py_VISIT(co->result);\r
- return 0;\r
-}\r
-\r
-static PyObject *\r
-cwr_next(cwrobject *co)\r
-{\r
- PyObject *elem;\r
- PyObject *oldelem;\r
- PyObject *pool = co->pool;\r
- Py_ssize_t *indices = co->indices;\r
- PyObject *result = co->result;\r
- Py_ssize_t n = PyTuple_GET_SIZE(pool);\r
- Py_ssize_t r = co->r;\r
- Py_ssize_t i, j, index;\r
-\r
- if (co->stopped)\r
- return NULL;\r
-\r
- if (result == NULL) {\r
- /* On the first pass, initialize result tuple using the indices */\r
- result = PyTuple_New(r);\r
- if (result == NULL)\r
- goto empty;\r
- co->result = result;\r
- for (i=0; i<r ; i++) {\r
- index = indices[i];\r
- elem = PyTuple_GET_ITEM(pool, index);\r
- Py_INCREF(elem);\r
- PyTuple_SET_ITEM(result, i, elem);\r
- }\r
- } else {\r
- /* Copy the previous result tuple or re-use it if available */\r
- if (Py_REFCNT(result) > 1) {\r
- PyObject *old_result = result;\r
- result = PyTuple_New(r);\r
- if (result == NULL)\r
- goto empty;\r
- co->result = result;\r
- for (i=0; i<r ; i++) {\r
- elem = PyTuple_GET_ITEM(old_result, i);\r
- Py_INCREF(elem);\r
- PyTuple_SET_ITEM(result, i, elem);\r
- }\r
- Py_DECREF(old_result);\r
- }\r
- /* Now, we've got the only copy so we can update it in-place CPython's\r
- empty tuple is a singleton and cached in PyTuple's freelist. */\r
- assert(r == 0 || Py_REFCNT(result) == 1);\r
-\r
- /* Scan indices right-to-left until finding one that is not\r
- * at its maximum (n-1). */\r
- for (i=r-1 ; i >= 0 && indices[i] == n-1; i--)\r
- ;\r
-\r
- /* If i is negative, then the indices are all at\r
- their maximum value and we're done. */\r
- if (i < 0)\r
- goto empty;\r
-\r
- /* Increment the current index which we know is not at its\r
- maximum. Then set all to the right to the same value. */\r
- indices[i]++;\r
- for (j=i+1 ; j<r ; j++)\r
- indices[j] = indices[j-1];\r
-\r
- /* Update the result tuple for the new indices\r
- starting with i, the leftmost index that changed */\r
- for ( ; i<r ; i++) {\r
- index = indices[i];\r
- elem = PyTuple_GET_ITEM(pool, index);\r
- Py_INCREF(elem);\r
- oldelem = PyTuple_GET_ITEM(result, i);\r
- PyTuple_SET_ITEM(result, i, elem);\r
- Py_DECREF(oldelem);\r
- }\r
- }\r
-\r
- Py_INCREF(result);\r
- return result;\r
-\r
-empty:\r
- co->stopped = 1;\r
- return NULL;\r
-}\r
-\r
-PyDoc_STRVAR(cwr_doc,\r
-"combinations_with_replacement(iterable, r) --> combinations_with_replacement object\n\\r
-\n\\r
-Return successive r-length combinations of elements in the iterable\n\\r
-allowing individual elements to have successive repeats.\n\\r
-combinations_with_replacement('ABC', 2) --> AA AB AC BB BC CC");\r
-\r
-static PyTypeObject cwr_type = {\r
- PyVarObject_HEAD_INIT(NULL, 0)\r
- "itertools.combinations_with_replacement", /* tp_name */\r
- sizeof(cwrobject), /* tp_basicsize */\r
- 0, /* tp_itemsize */\r
- /* methods */\r
- (destructor)cwr_dealloc, /* tp_dealloc */\r
- 0, /* tp_print */\r
- 0, /* tp_getattr */\r
- 0, /* tp_setattr */\r
- 0, /* tp_compare */\r
- 0, /* tp_repr */\r
- 0, /* tp_as_number */\r
- 0, /* tp_as_sequence */\r
- 0, /* tp_as_mapping */\r
- 0, /* tp_hash */\r
- 0, /* tp_call */\r
- 0, /* tp_str */\r
- PyObject_GenericGetAttr, /* tp_getattro */\r
- 0, /* tp_setattro */\r
- 0, /* tp_as_buffer */\r
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |\r
- Py_TPFLAGS_BASETYPE, /* tp_flags */\r
- cwr_doc, /* tp_doc */\r
- (traverseproc)cwr_traverse, /* tp_traverse */\r
- 0, /* tp_clear */\r
- 0, /* tp_richcompare */\r
- 0, /* tp_weaklistoffset */\r
- PyObject_SelfIter, /* tp_iter */\r
- (iternextfunc)cwr_next, /* tp_iternext */\r
- 0, /* tp_methods */\r
- 0, /* tp_members */\r
- 0, /* tp_getset */\r
- 0, /* tp_base */\r
- 0, /* tp_dict */\r
- 0, /* tp_descr_get */\r
- 0, /* tp_descr_set */\r
- 0, /* tp_dictoffset */\r
- 0, /* tp_init */\r
- 0, /* tp_alloc */\r
- cwr_new, /* tp_new */\r
- PyObject_GC_Del, /* tp_free */\r
-};\r
-\r
-\r
-/* permutations object ************************************************************\r
-\r
-def permutations(iterable, r=None):\r
- 'permutations(range(3), 2) --> (0,1) (0,2) (1,0) (1,2) (2,0) (2,1)'\r
- pool = tuple(iterable)\r
- n = len(pool)\r
- r = n if r is None else r\r
- indices = range(n)\r
- cycles = range(n-r+1, n+1)[::-1]\r
- yield tuple(pool[i] for i in indices[:r])\r
- while n:\r
- for i in reversed(range(r)):\r
- cycles[i] -= 1\r
- if cycles[i] == 0:\r
- indices[i:] = indices[i+1:] + indices[i:i+1]\r
- cycles[i] = n - i\r
- else:\r
- j = cycles[i]\r
- indices[i], indices[-j] = indices[-j], indices[i]\r
- yield tuple(pool[i] for i in indices[:r])\r
- break\r
- else:\r
- return\r
-*/\r
-\r
-typedef struct {\r
- PyObject_HEAD\r
- PyObject *pool; /* input converted to a tuple */\r
- Py_ssize_t *indices; /* one index per element in the pool */\r
- Py_ssize_t *cycles; /* one rollover counter per element in the result */\r
- PyObject *result; /* most recently returned result tuple */\r
- Py_ssize_t r; /* size of result tuple */\r
- int stopped; /* set to 1 when the permutations iterator is exhausted */\r
-} permutationsobject;\r
-\r
-static PyTypeObject permutations_type;\r
-\r
-static PyObject *\r
-permutations_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
-{\r
- permutationsobject *po;\r
- Py_ssize_t n;\r
- Py_ssize_t r;\r
- PyObject *robj = Py_None;\r
- PyObject *pool = NULL;\r
- PyObject *iterable = NULL;\r
- Py_ssize_t *indices = NULL;\r
- Py_ssize_t *cycles = NULL;\r
- Py_ssize_t i;\r
- static char *kwargs[] = {"iterable", "r", NULL};\r
-\r
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:permutations", kwargs,\r
- &iterable, &robj))\r
- return NULL;\r
-\r
- pool = PySequence_Tuple(iterable);\r
- if (pool == NULL)\r
- goto error;\r
- n = PyTuple_GET_SIZE(pool);\r
-\r
- r = n;\r
- if (robj != Py_None) {\r
- r = PyInt_AsSsize_t(robj);\r
- if (r == -1 && PyErr_Occurred())\r
- goto error;\r
- }\r
- if (r < 0) {\r
- PyErr_SetString(PyExc_ValueError, "r must be non-negative");\r
- goto error;\r
- }\r
-\r
- indices = PyMem_New(Py_ssize_t, n);\r
- cycles = PyMem_New(Py_ssize_t, r);\r
- if (indices == NULL || cycles == NULL) {\r
- PyErr_NoMemory();\r
- goto error;\r
- }\r
-\r
- for (i=0 ; i<n ; i++)\r
- indices[i] = i;\r
- for (i=0 ; i<r ; i++)\r
- cycles[i] = n - i;\r
-\r
- /* create permutationsobject structure */\r
- po = (permutationsobject *)type->tp_alloc(type, 0);\r
- if (po == NULL)\r
- goto error;\r
-\r
- po->pool = pool;\r
- po->indices = indices;\r
- po->cycles = cycles;\r
- po->result = NULL;\r
- po->r = r;\r
- po->stopped = r > n ? 1 : 0;\r
-\r
- return (PyObject *)po;\r
-\r
-error:\r
- if (indices != NULL)\r
- PyMem_Free(indices);\r
- if (cycles != NULL)\r
- PyMem_Free(cycles);\r
- Py_XDECREF(pool);\r
- return NULL;\r
-}\r
-\r
-static void\r
-permutations_dealloc(permutationsobject *po)\r
-{\r
- PyObject_GC_UnTrack(po);\r
- Py_XDECREF(po->pool);\r
- Py_XDECREF(po->result);\r
- PyMem_Free(po->indices);\r
- PyMem_Free(po->cycles);\r
- Py_TYPE(po)->tp_free(po);\r
-}\r
-\r
-static int\r
-permutations_traverse(permutationsobject *po, visitproc visit, void *arg)\r
-{\r
- Py_VISIT(po->pool);\r
- Py_VISIT(po->result);\r
- return 0;\r
-}\r
-\r
-static PyObject *\r
-permutations_next(permutationsobject *po)\r
-{\r
- PyObject *elem;\r
- PyObject *oldelem;\r
- PyObject *pool = po->pool;\r
- Py_ssize_t *indices = po->indices;\r
- Py_ssize_t *cycles = po->cycles;\r
- PyObject *result = po->result;\r
- Py_ssize_t n = PyTuple_GET_SIZE(pool);\r
- Py_ssize_t r = po->r;\r
- Py_ssize_t i, j, k, index;\r
-\r
- if (po->stopped)\r
- return NULL;\r
-\r
- if (result == NULL) {\r
- /* On the first pass, initialize result tuple using the indices */\r
- result = PyTuple_New(r);\r
- if (result == NULL)\r
- goto empty;\r
- po->result = result;\r
- for (i=0; i<r ; i++) {\r
- index = indices[i];\r
- elem = PyTuple_GET_ITEM(pool, index);\r
- Py_INCREF(elem);\r
- PyTuple_SET_ITEM(result, i, elem);\r
- }\r
- } else {\r
- if (n == 0)\r
- goto empty;\r
-\r
- /* Copy the previous result tuple or re-use it if available */\r
- if (Py_REFCNT(result) > 1) {\r
- PyObject *old_result = result;\r
- result = PyTuple_New(r);\r
- if (result == NULL)\r
- goto empty;\r
- po->result = result;\r
- for (i=0; i<r ; i++) {\r
- elem = PyTuple_GET_ITEM(old_result, i);\r
- Py_INCREF(elem);\r
- PyTuple_SET_ITEM(result, i, elem);\r
- }\r
- Py_DECREF(old_result);\r
- }\r
- /* Now, we've got the only copy so we can update it in-place */\r
- assert(r == 0 || Py_REFCNT(result) == 1);\r
-\r
- /* Decrement rightmost cycle, moving leftward upon zero rollover */\r
- for (i=r-1 ; i>=0 ; i--) {\r
- cycles[i] -= 1;\r
- if (cycles[i] == 0) {\r
- /* rotatation: indices[i:] = indices[i+1:] + indices[i:i+1] */\r
- index = indices[i];\r
- for (j=i ; j<n-1 ; j++)\r
- indices[j] = indices[j+1];\r
- indices[n-1] = index;\r
- cycles[i] = n - i;\r
- } else {\r
- j = cycles[i];\r
- index = indices[i];\r
- indices[i] = indices[n-j];\r
- indices[n-j] = index;\r
-\r
- for (k=i; k<r ; k++) {\r
- /* start with i, the leftmost element that changed */\r
- /* yield tuple(pool[k] for k in indices[:r]) */\r
- index = indices[k];\r
- elem = PyTuple_GET_ITEM(pool, index);\r
- Py_INCREF(elem);\r
- oldelem = PyTuple_GET_ITEM(result, k);\r
- PyTuple_SET_ITEM(result, k, elem);\r
- Py_DECREF(oldelem);\r
- }\r
- break;\r
- }\r
- }\r
- /* If i is negative, then the cycles have all\r
- rolled-over and we're done. */\r
- if (i < 0)\r
- goto empty;\r
- }\r
- Py_INCREF(result);\r
- return result;\r
-\r
-empty:\r
- po->stopped = 1;\r
- return NULL;\r
-}\r
-\r
-PyDoc_STRVAR(permutations_doc,\r
-"permutations(iterable[, r]) --> permutations object\n\\r
-\n\\r
-Return successive r-length permutations of elements in the iterable.\n\n\\r
-permutations(range(3), 2) --> (0,1), (0,2), (1,0), (1,2), (2,0), (2,1)");\r
-\r
-static PyTypeObject permutations_type = {\r
- PyVarObject_HEAD_INIT(NULL, 0)\r
- "itertools.permutations", /* tp_name */\r
- sizeof(permutationsobject), /* tp_basicsize */\r
- 0, /* tp_itemsize */\r
- /* methods */\r
- (destructor)permutations_dealloc, /* tp_dealloc */\r
- 0, /* tp_print */\r
- 0, /* tp_getattr */\r
- 0, /* tp_setattr */\r
- 0, /* tp_compare */\r
- 0, /* tp_repr */\r
- 0, /* tp_as_number */\r
- 0, /* tp_as_sequence */\r
- 0, /* tp_as_mapping */\r
- 0, /* tp_hash */\r
- 0, /* tp_call */\r
- 0, /* tp_str */\r
- PyObject_GenericGetAttr, /* tp_getattro */\r
- 0, /* tp_setattro */\r
- 0, /* tp_as_buffer */\r
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |\r
- Py_TPFLAGS_BASETYPE, /* tp_flags */\r
- permutations_doc, /* tp_doc */\r
- (traverseproc)permutations_traverse, /* tp_traverse */\r
- 0, /* tp_clear */\r
- 0, /* tp_richcompare */\r
- 0, /* tp_weaklistoffset */\r
- PyObject_SelfIter, /* tp_iter */\r
- (iternextfunc)permutations_next, /* tp_iternext */\r
- 0, /* tp_methods */\r
- 0, /* tp_members */\r
- 0, /* tp_getset */\r
- 0, /* tp_base */\r
- 0, /* tp_dict */\r
- 0, /* tp_descr_get */\r
- 0, /* tp_descr_set */\r
- 0, /* tp_dictoffset */\r
- 0, /* tp_init */\r
- 0, /* tp_alloc */\r
- permutations_new, /* tp_new */\r
- PyObject_GC_Del, /* tp_free */\r
-};\r
-\r
-\r
-/* compress object ************************************************************/\r
-\r
-/* Equivalent to:\r
-\r
- def compress(data, selectors):\r
- "compress('ABCDEF', [1,0,1,0,1,1]) --> A C E F"\r
- return (d for d, s in izip(data, selectors) if s)\r
-*/\r
-\r
-typedef struct {\r
- PyObject_HEAD\r
- PyObject *data;\r
- PyObject *selectors;\r
-} compressobject;\r
-\r
-static PyTypeObject compress_type;\r
-\r
-static PyObject *\r
-compress_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
-{\r
- PyObject *seq1, *seq2;\r
- PyObject *data=NULL, *selectors=NULL;\r
- compressobject *lz;\r
- static char *kwargs[] = {"data", "selectors", NULL};\r
-\r
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO:compress", kwargs, &seq1, &seq2))\r
- return NULL;\r
-\r
- data = PyObject_GetIter(seq1);\r
- if (data == NULL)\r
- goto fail;\r
- selectors = PyObject_GetIter(seq2);\r
- if (selectors == NULL)\r
- goto fail;\r
-\r
- /* create compressobject structure */\r
- lz = (compressobject *)type->tp_alloc(type, 0);\r
- if (lz == NULL)\r
- goto fail;\r
- lz->data = data;\r
- lz->selectors = selectors;\r
- return (PyObject *)lz;\r
-\r
-fail:\r
- Py_XDECREF(data);\r
- Py_XDECREF(selectors);\r
- return NULL;\r
-}\r
-\r
-static void\r
-compress_dealloc(compressobject *lz)\r
-{\r
- PyObject_GC_UnTrack(lz);\r
- Py_XDECREF(lz->data);\r
- Py_XDECREF(lz->selectors);\r
- Py_TYPE(lz)->tp_free(lz);\r
-}\r
-\r
-static int\r
-compress_traverse(compressobject *lz, visitproc visit, void *arg)\r
-{\r
- Py_VISIT(lz->data);\r
- Py_VISIT(lz->selectors);\r
- return 0;\r
-}\r
-\r
-static PyObject *\r
-compress_next(compressobject *lz)\r
-{\r
- PyObject *data = lz->data, *selectors = lz->selectors;\r
- PyObject *datum, *selector;\r
- PyObject *(*datanext)(PyObject *) = *Py_TYPE(data)->tp_iternext;\r
- PyObject *(*selectornext)(PyObject *) = *Py_TYPE(selectors)->tp_iternext;\r
- int ok;\r
-\r
- while (1) {\r
- /* Steps: get datum, get selector, evaluate selector.\r
- Order is important (to match the pure python version\r
- in terms of which input gets a chance to raise an\r
- exception first).\r
- */\r
-\r
- datum = datanext(data);\r
- if (datum == NULL)\r
- return NULL;\r
-\r
- selector = selectornext(selectors);\r
- if (selector == NULL) {\r
- Py_DECREF(datum);\r
- return NULL;\r
- }\r
-\r
- ok = PyObject_IsTrue(selector);\r
- Py_DECREF(selector);\r
- if (ok == 1)\r
- return datum;\r
- Py_DECREF(datum);\r
- if (ok == -1)\r
- return NULL;\r
- }\r
-}\r
-\r
-PyDoc_STRVAR(compress_doc,\r
-"compress(data, selectors) --> iterator over selected data\n\\r
-\n\\r
-Return data elements corresponding to true selector elements.\n\\r
-Forms a shorter iterator from selected data elements using the\n\\r
-selectors to choose the data elements.");\r
-\r
-static PyTypeObject compress_type = {\r
- PyVarObject_HEAD_INIT(NULL, 0)\r
- "itertools.compress", /* tp_name */\r
- sizeof(compressobject), /* tp_basicsize */\r
- 0, /* tp_itemsize */\r
- /* methods */\r
- (destructor)compress_dealloc, /* tp_dealloc */\r
- 0, /* tp_print */\r
- 0, /* tp_getattr */\r
- 0, /* tp_setattr */\r
- 0, /* tp_compare */\r
- 0, /* tp_repr */\r
- 0, /* tp_as_number */\r
- 0, /* tp_as_sequence */\r
- 0, /* tp_as_mapping */\r
- 0, /* tp_hash */\r
- 0, /* tp_call */\r
- 0, /* tp_str */\r
- PyObject_GenericGetAttr, /* tp_getattro */\r
- 0, /* tp_setattro */\r
- 0, /* tp_as_buffer */\r
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |\r
- Py_TPFLAGS_BASETYPE, /* tp_flags */\r
- compress_doc, /* tp_doc */\r
- (traverseproc)compress_traverse, /* tp_traverse */\r
- 0, /* tp_clear */\r
- 0, /* tp_richcompare */\r
- 0, /* tp_weaklistoffset */\r
- PyObject_SelfIter, /* tp_iter */\r
- (iternextfunc)compress_next, /* tp_iternext */\r
- 0, /* tp_methods */\r
- 0, /* tp_members */\r
- 0, /* tp_getset */\r
- 0, /* tp_base */\r
- 0, /* tp_dict */\r
- 0, /* tp_descr_get */\r
- 0, /* tp_descr_set */\r
- 0, /* tp_dictoffset */\r
- 0, /* tp_init */\r
- 0, /* tp_alloc */\r
- compress_new, /* tp_new */\r
- PyObject_GC_Del, /* tp_free */\r
-};\r
-\r
-\r
-/* ifilter object ************************************************************/\r
-\r
-typedef struct {\r
- PyObject_HEAD\r
- PyObject *func;\r
- PyObject *it;\r
-} ifilterobject;\r
-\r
-static PyTypeObject ifilter_type;\r
-\r
-static PyObject *\r
-ifilter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
-{\r
- PyObject *func, *seq;\r
- PyObject *it;\r
- ifilterobject *lz;\r
-\r
- if (type == &ifilter_type && !_PyArg_NoKeywords("ifilter()", kwds))\r
- return NULL;\r
-\r
- if (!PyArg_UnpackTuple(args, "ifilter", 2, 2, &func, &seq))\r
- return NULL;\r
-\r
- /* Get iterator. */\r
- it = PyObject_GetIter(seq);\r
- if (it == NULL)\r
- return NULL;\r
-\r
- /* create ifilterobject structure */\r
- lz = (ifilterobject *)type->tp_alloc(type, 0);\r
- if (lz == NULL) {\r
- Py_DECREF(it);\r
- return NULL;\r
- }\r
- Py_INCREF(func);\r
- lz->func = func;\r
- lz->it = it;\r
-\r
- return (PyObject *)lz;\r
-}\r
-\r
-static void\r
-ifilter_dealloc(ifilterobject *lz)\r
-{\r
- PyObject_GC_UnTrack(lz);\r
- Py_XDECREF(lz->func);\r
- Py_XDECREF(lz->it);\r
- Py_TYPE(lz)->tp_free(lz);\r
-}\r
-\r
-static int\r
-ifilter_traverse(ifilterobject *lz, visitproc visit, void *arg)\r
-{\r
- Py_VISIT(lz->it);\r
- Py_VISIT(lz->func);\r
- return 0;\r
-}\r
-\r
-static PyObject *\r
-ifilter_next(ifilterobject *lz)\r
-{\r
- PyObject *item;\r
- PyObject *it = lz->it;\r
- long ok;\r
- PyObject *(*iternext)(PyObject *);\r
-\r
- iternext = *Py_TYPE(it)->tp_iternext;\r
- for (;;) {\r
- item = iternext(it);\r
- if (item == NULL)\r
- return NULL;\r
-\r
- if (lz->func == Py_None || lz->func == (PyObject *)&PyBool_Type) {\r
- ok = PyObject_IsTrue(item);\r
- } else {\r
- PyObject *good;\r
- good = PyObject_CallFunctionObjArgs(lz->func,\r
- item, NULL);\r
- if (good == NULL) {\r
- Py_DECREF(item);\r
- return NULL;\r
- }\r
- ok = PyObject_IsTrue(good);\r
- Py_DECREF(good);\r
- }\r
- if (ok > 0)\r
- return item;\r
- Py_DECREF(item);\r
- if (ok < 0)\r
- return NULL;\r
- }\r
-}\r
-\r
-PyDoc_STRVAR(ifilter_doc,\r
-"ifilter(function or None, sequence) --> ifilter object\n\\r
-\n\\r
-Return those items of sequence for which function(item) is true.\n\\r
-If function is None, return the items that are true.");\r
-\r
-static PyTypeObject ifilter_type = {\r
- PyVarObject_HEAD_INIT(NULL, 0)\r
- "itertools.ifilter", /* tp_name */\r
- sizeof(ifilterobject), /* tp_basicsize */\r
- 0, /* tp_itemsize */\r
- /* methods */\r
- (destructor)ifilter_dealloc, /* tp_dealloc */\r
- 0, /* tp_print */\r
- 0, /* tp_getattr */\r
- 0, /* tp_setattr */\r
- 0, /* tp_compare */\r
- 0, /* tp_repr */\r
- 0, /* tp_as_number */\r
- 0, /* tp_as_sequence */\r
- 0, /* tp_as_mapping */\r
- 0, /* tp_hash */\r
- 0, /* tp_call */\r
- 0, /* tp_str */\r
- PyObject_GenericGetAttr, /* tp_getattro */\r
- 0, /* tp_setattro */\r
- 0, /* tp_as_buffer */\r
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |\r
- Py_TPFLAGS_BASETYPE, /* tp_flags */\r
- ifilter_doc, /* tp_doc */\r
- (traverseproc)ifilter_traverse, /* tp_traverse */\r
- 0, /* tp_clear */\r
- 0, /* tp_richcompare */\r
- 0, /* tp_weaklistoffset */\r
- PyObject_SelfIter, /* tp_iter */\r
- (iternextfunc)ifilter_next, /* tp_iternext */\r
- 0, /* tp_methods */\r
- 0, /* tp_members */\r
- 0, /* tp_getset */\r
- 0, /* tp_base */\r
- 0, /* tp_dict */\r
- 0, /* tp_descr_get */\r
- 0, /* tp_descr_set */\r
- 0, /* tp_dictoffset */\r
- 0, /* tp_init */\r
- 0, /* tp_alloc */\r
- ifilter_new, /* tp_new */\r
- PyObject_GC_Del, /* tp_free */\r
-};\r
-\r
-\r
-/* ifilterfalse object ************************************************************/\r
-\r
-typedef struct {\r
- PyObject_HEAD\r
- PyObject *func;\r
- PyObject *it;\r
-} ifilterfalseobject;\r
-\r
-static PyTypeObject ifilterfalse_type;\r
-\r
-static PyObject *\r
-ifilterfalse_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
-{\r
- PyObject *func, *seq;\r
- PyObject *it;\r
- ifilterfalseobject *lz;\r
-\r
- if (type == &ifilterfalse_type &&\r
- !_PyArg_NoKeywords("ifilterfalse()", kwds))\r
- return NULL;\r
-\r
- if (!PyArg_UnpackTuple(args, "ifilterfalse", 2, 2, &func, &seq))\r
- return NULL;\r
-\r
- /* Get iterator. */\r
- it = PyObject_GetIter(seq);\r
- if (it == NULL)\r
- return NULL;\r
-\r
- /* create ifilterfalseobject structure */\r
- lz = (ifilterfalseobject *)type->tp_alloc(type, 0);\r
- if (lz == NULL) {\r
- Py_DECREF(it);\r
- return NULL;\r
- }\r
- Py_INCREF(func);\r
- lz->func = func;\r
- lz->it = it;\r
-\r
- return (PyObject *)lz;\r
-}\r
-\r
-static void\r
-ifilterfalse_dealloc(ifilterfalseobject *lz)\r
-{\r
- PyObject_GC_UnTrack(lz);\r
- Py_XDECREF(lz->func);\r
- Py_XDECREF(lz->it);\r
- Py_TYPE(lz)->tp_free(lz);\r
-}\r
-\r
-static int\r
-ifilterfalse_traverse(ifilterfalseobject *lz, visitproc visit, void *arg)\r
-{\r
- Py_VISIT(lz->it);\r
- Py_VISIT(lz->func);\r
- return 0;\r
-}\r
-\r
-static PyObject *\r
-ifilterfalse_next(ifilterfalseobject *lz)\r
-{\r
- PyObject *item;\r
- PyObject *it = lz->it;\r
- long ok;\r
- PyObject *(*iternext)(PyObject *);\r
-\r
- iternext = *Py_TYPE(it)->tp_iternext;\r
- for (;;) {\r
- item = iternext(it);\r
- if (item == NULL)\r
- return NULL;\r
-\r
- if (lz->func == Py_None || lz->func == (PyObject *)&PyBool_Type) {\r
- ok = PyObject_IsTrue(item);\r
- } else {\r
- PyObject *good;\r
- good = PyObject_CallFunctionObjArgs(lz->func,\r
- item, NULL);\r
- if (good == NULL) {\r
- Py_DECREF(item);\r
- return NULL;\r
- }\r
- ok = PyObject_IsTrue(good);\r
- Py_DECREF(good);\r
- }\r
- if (ok == 0)\r
- return item;\r
- Py_DECREF(item);\r
- if (ok < 0)\r
- return NULL;\r
- }\r
-}\r
-\r
-PyDoc_STRVAR(ifilterfalse_doc,\r
-"ifilterfalse(function or None, sequence) --> ifilterfalse object\n\\r
-\n\\r
-Return those items of sequence for which function(item) is false.\n\\r
-If function is None, return the items that are false.");\r
-\r
-static PyTypeObject ifilterfalse_type = {\r
- PyVarObject_HEAD_INIT(NULL, 0)\r
- "itertools.ifilterfalse", /* tp_name */\r
- sizeof(ifilterfalseobject), /* tp_basicsize */\r
- 0, /* tp_itemsize */\r
- /* methods */\r
- (destructor)ifilterfalse_dealloc, /* tp_dealloc */\r
- 0, /* tp_print */\r
- 0, /* tp_getattr */\r
- 0, /* tp_setattr */\r
- 0, /* tp_compare */\r
- 0, /* tp_repr */\r
- 0, /* tp_as_number */\r
- 0, /* tp_as_sequence */\r
- 0, /* tp_as_mapping */\r
- 0, /* tp_hash */\r
- 0, /* tp_call */\r
- 0, /* tp_str */\r
- PyObject_GenericGetAttr, /* tp_getattro */\r
- 0, /* tp_setattro */\r
- 0, /* tp_as_buffer */\r
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |\r
- Py_TPFLAGS_BASETYPE, /* tp_flags */\r
- ifilterfalse_doc, /* tp_doc */\r
- (traverseproc)ifilterfalse_traverse, /* tp_traverse */\r
- 0, /* tp_clear */\r
- 0, /* tp_richcompare */\r
- 0, /* tp_weaklistoffset */\r
- PyObject_SelfIter, /* tp_iter */\r
- (iternextfunc)ifilterfalse_next, /* tp_iternext */\r
- 0, /* tp_methods */\r
- 0, /* tp_members */\r
- 0, /* tp_getset */\r
- 0, /* tp_base */\r
- 0, /* tp_dict */\r
- 0, /* tp_descr_get */\r
- 0, /* tp_descr_set */\r
- 0, /* tp_dictoffset */\r
- 0, /* tp_init */\r
- 0, /* tp_alloc */\r
- ifilterfalse_new, /* tp_new */\r
- PyObject_GC_Del, /* tp_free */\r
-};\r
-\r
-\r
-/* count object ************************************************************/\r
-\r
-typedef struct {\r
- PyObject_HEAD\r
- Py_ssize_t cnt;\r
- PyObject *long_cnt;\r
- PyObject *long_step;\r
-} countobject;\r
-\r
-/* Counting logic and invariants:\r
-\r
-fast_mode: when cnt an integer < PY_SSIZE_T_MAX and no step is specified.\r
-\r
- assert(cnt != PY_SSIZE_T_MAX && long_cnt == NULL && long_step==PyInt(1));\r
- Advances with: cnt += 1\r
- When count hits Y_SSIZE_T_MAX, switch to slow_mode.\r
-\r
-slow_mode: when cnt == PY_SSIZE_T_MAX, step is not int(1), or cnt is a float.\r
-\r
- assert(cnt == PY_SSIZE_T_MAX && long_cnt != NULL && long_step != NULL);\r
- All counting is done with python objects (no overflows or underflows).\r
- Advances with: long_cnt += long_step\r
- Step may be zero -- effectively a slow version of repeat(cnt).\r
- Either long_cnt or long_step may be a float, Fraction, or Decimal.\r
-*/\r
-\r
-static PyTypeObject count_type;\r
-\r
-static PyObject *\r
-count_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
-{\r
- countobject *lz;\r
- int slow_mode = 0;\r
- Py_ssize_t cnt = 0;\r
- PyObject *long_cnt = NULL;\r
- PyObject *long_step = NULL;\r
- static char *kwlist[] = {"start", "step", 0};\r
-\r
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO:count",\r
- kwlist, &long_cnt, &long_step))\r
- return NULL;\r
-\r
- if ((long_cnt != NULL && !PyNumber_Check(long_cnt)) ||\r
- (long_step != NULL && !PyNumber_Check(long_step))) {\r
- PyErr_SetString(PyExc_TypeError, "a number is required");\r
- return NULL;\r
- }\r
-\r
- if (long_cnt != NULL) {\r
- cnt = PyInt_AsSsize_t(long_cnt);\r
- if ((cnt == -1 && PyErr_Occurred()) || !PyInt_Check(long_cnt)) {\r
- PyErr_Clear();\r
- slow_mode = 1;\r
- }\r
- Py_INCREF(long_cnt);\r
- } else {\r
- cnt = 0;\r
- long_cnt = PyInt_FromLong(0);\r
- }\r
-\r
- /* If not specified, step defaults to 1 */\r
- if (long_step == NULL) {\r
- long_step = PyInt_FromLong(1);\r
- if (long_step == NULL) {\r
- Py_DECREF(long_cnt);\r
- return NULL;\r
- }\r
- } else\r
- Py_INCREF(long_step);\r
-\r
- assert(long_cnt != NULL && long_step != NULL);\r
-\r
- /* Fast mode only works when the step is 1 */\r
- if (!PyInt_Check(long_step) ||\r
- PyInt_AS_LONG(long_step) != 1) {\r
- slow_mode = 1;\r
- }\r
-\r
- if (slow_mode)\r
- cnt = PY_SSIZE_T_MAX;\r
- else\r
- Py_CLEAR(long_cnt);\r
-\r
- assert((cnt != PY_SSIZE_T_MAX && long_cnt == NULL && !slow_mode) ||\r
- (cnt == PY_SSIZE_T_MAX && long_cnt != NULL && slow_mode));\r
- assert(slow_mode ||\r
- (PyInt_Check(long_step) && PyInt_AS_LONG(long_step) == 1));\r
-\r
- /* create countobject structure */\r
- lz = (countobject *)type->tp_alloc(type, 0);\r
- if (lz == NULL) {\r
- Py_XDECREF(long_cnt);\r
- return NULL;\r
- }\r
- lz->cnt = cnt;\r
- lz->long_cnt = long_cnt;\r
- lz->long_step = long_step;\r
-\r
- return (PyObject *)lz;\r
-}\r
-\r
-static void\r
-count_dealloc(countobject *lz)\r
-{\r
- PyObject_GC_UnTrack(lz);\r
- Py_XDECREF(lz->long_cnt);\r
- Py_XDECREF(lz->long_step);\r
- Py_TYPE(lz)->tp_free(lz);\r
-}\r
-\r
-static int\r
-count_traverse(countobject *lz, visitproc visit, void *arg)\r
-{\r
- Py_VISIT(lz->long_cnt);\r
- Py_VISIT(lz->long_step);\r
- return 0;\r
-}\r
-\r
-static PyObject *\r
-count_nextlong(countobject *lz)\r
-{\r
- PyObject *long_cnt;\r
- PyObject *stepped_up;\r
-\r
- long_cnt = lz->long_cnt;\r
- if (long_cnt == NULL) {\r
- /* Switch to slow_mode */\r
- long_cnt = PyInt_FromSsize_t(PY_SSIZE_T_MAX);\r
- if (long_cnt == NULL)\r
- return NULL;\r
- }\r
- assert(lz->cnt == PY_SSIZE_T_MAX && long_cnt != NULL);\r
-\r
- stepped_up = PyNumber_Add(long_cnt, lz->long_step);\r
- if (stepped_up == NULL)\r
- return NULL;\r
- lz->long_cnt = stepped_up;\r
- return long_cnt;\r
-}\r
-\r
-static PyObject *\r
-count_next(countobject *lz)\r
-{\r
- if (lz->cnt == PY_SSIZE_T_MAX)\r
- return count_nextlong(lz);\r
- return PyInt_FromSsize_t(lz->cnt++);\r
-}\r
-\r
-static PyObject *\r
-count_repr(countobject *lz)\r
-{\r
- PyObject *cnt_repr, *step_repr = NULL;\r
- PyObject *result = NULL;\r
-\r
- if (lz->cnt != PY_SSIZE_T_MAX)\r
- return PyString_FromFormat("count(%zd)", lz->cnt);\r
-\r
- cnt_repr = PyObject_Repr(lz->long_cnt);\r
- if (cnt_repr == NULL)\r
- return NULL;\r
-\r
- if (PyInt_Check(lz->long_step) && PyInt_AS_LONG(lz->long_step) == 1) {\r
- /* Don't display step when it is an integer equal to 1 */\r
- result = PyString_FromFormat("count(%s)",\r
- PyString_AS_STRING(cnt_repr));\r
- } else {\r
- step_repr = PyObject_Repr(lz->long_step);\r
- if (step_repr != NULL)\r
- result = PyString_FromFormat("count(%s, %s)",\r
- PyString_AS_STRING(cnt_repr),\r
- PyString_AS_STRING(step_repr));\r
- }\r
- Py_DECREF(cnt_repr);\r
- Py_XDECREF(step_repr);\r
- return result;\r
-}\r
-\r
-static PyObject *\r
-count_reduce(countobject *lz)\r
-{\r
- if (lz->cnt == PY_SSIZE_T_MAX)\r
- return Py_BuildValue("O(OO)", Py_TYPE(lz), lz->long_cnt, lz->long_step);\r
- return Py_BuildValue("O(n)", Py_TYPE(lz), lz->cnt);\r
-}\r
-\r
-PyDoc_STRVAR(count_reduce_doc, "Return state information for pickling.");\r
-\r
-static PyMethodDef count_methods[] = {\r
- {"__reduce__", (PyCFunction)count_reduce, METH_NOARGS,\r
- count_reduce_doc},\r
- {NULL, NULL} /* sentinel */\r
-};\r
-\r
-PyDoc_STRVAR(count_doc,\r
- "count(start=0, step=1) --> count object\n\\r
-\n\\r
-Return a count object whose .next() method returns consecutive values.\n\\r
-Equivalent to:\n\n\\r
- def count(firstval=0, step=1):\n\\r
- x = firstval\n\\r
- while 1:\n\\r
- yield x\n\\r
- x += step\n");\r
-\r
-static PyTypeObject count_type = {\r
- PyVarObject_HEAD_INIT(NULL, 0)\r
- "itertools.count", /* tp_name */\r
- sizeof(countobject), /* tp_basicsize */\r
- 0, /* tp_itemsize */\r
- /* methods */\r
- (destructor)count_dealloc, /* tp_dealloc */\r
- 0, /* tp_print */\r
- 0, /* tp_getattr */\r
- 0, /* tp_setattr */\r
- 0, /* tp_compare */\r
- (reprfunc)count_repr, /* tp_repr */\r
- 0, /* tp_as_number */\r
- 0, /* tp_as_sequence */\r
- 0, /* tp_as_mapping */\r
- 0, /* tp_hash */\r
- 0, /* tp_call */\r
- 0, /* tp_str */\r
- PyObject_GenericGetAttr, /* tp_getattro */\r
- 0, /* tp_setattro */\r
- 0, /* tp_as_buffer */\r
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |\r
- Py_TPFLAGS_BASETYPE, /* tp_flags */\r
- count_doc, /* tp_doc */\r
- (traverseproc)count_traverse, /* tp_traverse */\r
- 0, /* tp_clear */\r
- 0, /* tp_richcompare */\r
- 0, /* tp_weaklistoffset */\r
- PyObject_SelfIter, /* tp_iter */\r
- (iternextfunc)count_next, /* tp_iternext */\r
- count_methods, /* tp_methods */\r
- 0, /* tp_members */\r
- 0, /* tp_getset */\r
- 0, /* tp_base */\r
- 0, /* tp_dict */\r
- 0, /* tp_descr_get */\r
- 0, /* tp_descr_set */\r
- 0, /* tp_dictoffset */\r
- 0, /* tp_init */\r
- 0, /* tp_alloc */\r
- count_new, /* tp_new */\r
- PyObject_GC_Del, /* tp_free */\r
-};\r
-\r
-\r
-/* izip object ************************************************************/\r
-\r
-#include "Python.h"\r
-\r
-typedef struct {\r
- PyObject_HEAD\r
- Py_ssize_t tuplesize;\r
- PyObject *ittuple; /* tuple of iterators */\r
- PyObject *result;\r
-} izipobject;\r
-\r
-static PyTypeObject izip_type;\r
-\r
-static PyObject *\r
-izip_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
-{\r
- izipobject *lz;\r
- Py_ssize_t i;\r
- PyObject *ittuple; /* tuple of iterators */\r
- PyObject *result;\r
- Py_ssize_t tuplesize = PySequence_Length(args);\r
-\r
- if (type == &izip_type && !_PyArg_NoKeywords("izip()", kwds))\r
- return NULL;\r
-\r
- /* args must be a tuple */\r
- assert(PyTuple_Check(args));\r
-\r
- /* obtain iterators */\r
- ittuple = PyTuple_New(tuplesize);\r
- if (ittuple == NULL)\r
- return NULL;\r
- for (i=0; i < tuplesize; ++i) {\r
- PyObject *item = PyTuple_GET_ITEM(args, i);\r
- PyObject *it = PyObject_GetIter(item);\r
- if (it == NULL) {\r
- if (PyErr_ExceptionMatches(PyExc_TypeError))\r
- PyErr_Format(PyExc_TypeError,\r
- "izip argument #%zd must support iteration",\r
- i+1);\r
- Py_DECREF(ittuple);\r
- return NULL;\r
- }\r
- PyTuple_SET_ITEM(ittuple, i, it);\r
- }\r
-\r
- /* create a result holder */\r
- result = PyTuple_New(tuplesize);\r
- if (result == NULL) {\r
- Py_DECREF(ittuple);\r
- return NULL;\r
- }\r
- for (i=0 ; i < tuplesize ; i++) {\r
- Py_INCREF(Py_None);\r
- PyTuple_SET_ITEM(result, i, Py_None);\r
- }\r
-\r
- /* create izipobject structure */\r
- lz = (izipobject *)type->tp_alloc(type, 0);\r
- if (lz == NULL) {\r
- Py_DECREF(ittuple);\r
- Py_DECREF(result);\r
- return NULL;\r
- }\r
- lz->ittuple = ittuple;\r
- lz->tuplesize = tuplesize;\r
- lz->result = result;\r
-\r
- return (PyObject *)lz;\r
-}\r
-\r
-static void\r
-izip_dealloc(izipobject *lz)\r
-{\r
- PyObject_GC_UnTrack(lz);\r
- Py_XDECREF(lz->ittuple);\r
- Py_XDECREF(lz->result);\r
- Py_TYPE(lz)->tp_free(lz);\r
-}\r
-\r
-static int\r
-izip_traverse(izipobject *lz, visitproc visit, void *arg)\r
-{\r
- Py_VISIT(lz->ittuple);\r
- Py_VISIT(lz->result);\r
- return 0;\r
-}\r
-\r
-static PyObject *\r
-izip_next(izipobject *lz)\r
-{\r
- Py_ssize_t i;\r
- Py_ssize_t tuplesize = lz->tuplesize;\r
- PyObject *result = lz->result;\r
- PyObject *it;\r
- PyObject *item;\r
- PyObject *olditem;\r
-\r
- if (tuplesize == 0)\r
- return NULL;\r
- if (Py_REFCNT(result) == 1) {\r
- Py_INCREF(result);\r
- for (i=0 ; i < tuplesize ; i++) {\r
- it = PyTuple_GET_ITEM(lz->ittuple, i);\r
- item = (*Py_TYPE(it)->tp_iternext)(it);\r
- if (item == NULL) {\r
- Py_DECREF(result);\r
- return NULL;\r
- }\r
- olditem = PyTuple_GET_ITEM(result, i);\r
- PyTuple_SET_ITEM(result, i, item);\r
- Py_DECREF(olditem);\r
- }\r
- } else {\r
- result = PyTuple_New(tuplesize);\r
- if (result == NULL)\r
- return NULL;\r
- for (i=0 ; i < tuplesize ; i++) {\r
- it = PyTuple_GET_ITEM(lz->ittuple, i);\r
- item = (*Py_TYPE(it)->tp_iternext)(it);\r
- if (item == NULL) {\r
- Py_DECREF(result);\r
- return NULL;\r
- }\r
- PyTuple_SET_ITEM(result, i, item);\r
- }\r
- }\r
- return result;\r
-}\r
-\r
-PyDoc_STRVAR(izip_doc,\r
-"izip(iter1 [,iter2 [...]]) --> izip object\n\\r
-\n\\r
-Return a izip object whose .next() method returns a tuple where\n\\r
-the i-th element comes from the i-th iterable argument. The .next()\n\\r
-method continues until the shortest iterable in the argument sequence\n\\r
-is exhausted and then it raises StopIteration. Works like the zip()\n\\r
-function but consumes less memory by returning an iterator instead of\n\\r
-a list.");\r
-\r
-static PyTypeObject izip_type = {\r
- PyVarObject_HEAD_INIT(NULL, 0)\r
- "itertools.izip", /* tp_name */\r
- sizeof(izipobject), /* tp_basicsize */\r
- 0, /* tp_itemsize */\r
- /* methods */\r
- (destructor)izip_dealloc, /* tp_dealloc */\r
- 0, /* tp_print */\r
- 0, /* tp_getattr */\r
- 0, /* tp_setattr */\r
- 0, /* tp_compare */\r
- 0, /* tp_repr */\r
- 0, /* tp_as_number */\r
- 0, /* tp_as_sequence */\r
- 0, /* tp_as_mapping */\r
- 0, /* tp_hash */\r
- 0, /* tp_call */\r
- 0, /* tp_str */\r
- PyObject_GenericGetAttr, /* tp_getattro */\r
- 0, /* tp_setattro */\r
- 0, /* tp_as_buffer */\r
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |\r
- Py_TPFLAGS_BASETYPE, /* tp_flags */\r
- izip_doc, /* tp_doc */\r
- (traverseproc)izip_traverse, /* tp_traverse */\r
- 0, /* tp_clear */\r
- 0, /* tp_richcompare */\r
- 0, /* tp_weaklistoffset */\r
- PyObject_SelfIter, /* tp_iter */\r
- (iternextfunc)izip_next, /* tp_iternext */\r
- 0, /* tp_methods */\r
- 0, /* tp_members */\r
- 0, /* tp_getset */\r
- 0, /* tp_base */\r
- 0, /* tp_dict */\r
- 0, /* tp_descr_get */\r
- 0, /* tp_descr_set */\r
- 0, /* tp_dictoffset */\r
- 0, /* tp_init */\r
- 0, /* tp_alloc */\r
- izip_new, /* tp_new */\r
- PyObject_GC_Del, /* tp_free */\r
-};\r
-\r
-\r
-/* repeat object ************************************************************/\r
-\r
-typedef struct {\r
- PyObject_HEAD\r
- PyObject *element;\r
- Py_ssize_t cnt;\r
-} repeatobject;\r
-\r
-static PyTypeObject repeat_type;\r
-\r
-static PyObject *\r
-repeat_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
-{\r
- repeatobject *ro;\r
- PyObject *element;\r
- Py_ssize_t cnt = -1, n_kwds = 0;\r
- static char *kwargs[] = {"object", "times", NULL};\r
-\r
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:repeat", kwargs,\r
- &element, &cnt))\r
- return NULL;\r
-\r
- if (kwds != NULL)\r
- n_kwds = PyDict_Size(kwds);\r
- /* Does user supply times argument? */\r
- if ((PyTuple_Size(args) + n_kwds == 2) && cnt < 0)\r
- cnt = 0;\r
-\r
- ro = (repeatobject *)type->tp_alloc(type, 0);\r
- if (ro == NULL)\r
- return NULL;\r
- Py_INCREF(element);\r
- ro->element = element;\r
- ro->cnt = cnt;\r
- return (PyObject *)ro;\r
-}\r
-\r
-static void\r
-repeat_dealloc(repeatobject *ro)\r
-{\r
- PyObject_GC_UnTrack(ro);\r
- Py_XDECREF(ro->element);\r
- Py_TYPE(ro)->tp_free(ro);\r
-}\r
-\r
-static int\r
-repeat_traverse(repeatobject *ro, visitproc visit, void *arg)\r
-{\r
- Py_VISIT(ro->element);\r
- return 0;\r
-}\r
-\r
-static PyObject *\r
-repeat_next(repeatobject *ro)\r
-{\r
- if (ro->cnt == 0)\r
- return NULL;\r
- if (ro->cnt > 0)\r
- ro->cnt--;\r
- Py_INCREF(ro->element);\r
- return ro->element;\r
-}\r
-\r
-static PyObject *\r
-repeat_repr(repeatobject *ro)\r
-{\r
- PyObject *result, *objrepr;\r
-\r
- objrepr = PyObject_Repr(ro->element);\r
- if (objrepr == NULL)\r
- return NULL;\r
-\r
- if (ro->cnt == -1)\r
- result = PyString_FromFormat("repeat(%s)",\r
- PyString_AS_STRING(objrepr));\r
- else\r
- result = PyString_FromFormat("repeat(%s, %zd)",\r
- PyString_AS_STRING(objrepr), ro->cnt);\r
- Py_DECREF(objrepr);\r
- return result;\r
-}\r
-\r
-static PyObject *\r
-repeat_len(repeatobject *ro)\r
-{\r
- if (ro->cnt == -1) {\r
- PyErr_SetString(PyExc_TypeError, "len() of unsized object");\r
- return NULL;\r
- }\r
- return PyInt_FromSize_t(ro->cnt);\r
-}\r
-\r
-PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");\r
-\r
-static PyMethodDef repeat_methods[] = {\r
- {"__length_hint__", (PyCFunction)repeat_len, METH_NOARGS, length_hint_doc},\r
- {NULL, NULL} /* sentinel */\r
-};\r
-\r
-PyDoc_STRVAR(repeat_doc,\r
-"repeat(object [,times]) -> create an iterator which returns the object\n\\r
-for the specified number of times. If not specified, returns the object\n\\r
-endlessly.");\r
-\r
-static PyTypeObject repeat_type = {\r
- PyVarObject_HEAD_INIT(NULL, 0)\r
- "itertools.repeat", /* tp_name */\r
- sizeof(repeatobject), /* tp_basicsize */\r
- 0, /* tp_itemsize */\r
- /* methods */\r
- (destructor)repeat_dealloc, /* tp_dealloc */\r
- 0, /* tp_print */\r
- 0, /* tp_getattr */\r
- 0, /* tp_setattr */\r
- 0, /* tp_compare */\r
- (reprfunc)repeat_repr, /* tp_repr */\r
- 0, /* tp_as_number */\r
- 0, /* tp_as_sequence */\r
- 0, /* tp_as_mapping */\r
- 0, /* tp_hash */\r
- 0, /* tp_call */\r
- 0, /* tp_str */\r
- PyObject_GenericGetAttr, /* tp_getattro */\r
- 0, /* tp_setattro */\r
- 0, /* tp_as_buffer */\r
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |\r
- Py_TPFLAGS_BASETYPE, /* tp_flags */\r
- repeat_doc, /* tp_doc */\r
- (traverseproc)repeat_traverse, /* tp_traverse */\r
- 0, /* tp_clear */\r
- 0, /* tp_richcompare */\r
- 0, /* tp_weaklistoffset */\r
- PyObject_SelfIter, /* tp_iter */\r
- (iternextfunc)repeat_next, /* tp_iternext */\r
- repeat_methods, /* tp_methods */\r
- 0, /* tp_members */\r
- 0, /* tp_getset */\r
- 0, /* tp_base */\r
- 0, /* tp_dict */\r
- 0, /* tp_descr_get */\r
- 0, /* tp_descr_set */\r
- 0, /* tp_dictoffset */\r
- 0, /* tp_init */\r
- 0, /* tp_alloc */\r
- repeat_new, /* tp_new */\r
- PyObject_GC_Del, /* tp_free */\r
-};\r
-\r
-/* iziplongest object ************************************************************/\r
-\r
-#include "Python.h"\r
-\r
-typedef struct {\r
- PyObject_HEAD\r
- Py_ssize_t tuplesize;\r
- Py_ssize_t numactive;\r
- PyObject *ittuple; /* tuple of iterators */\r
- PyObject *result;\r
- PyObject *fillvalue;\r
-} iziplongestobject;\r
-\r
-static PyTypeObject iziplongest_type;\r
-\r
-static PyObject *\r
-izip_longest_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
-{\r
- iziplongestobject *lz;\r
- Py_ssize_t i;\r
- PyObject *ittuple; /* tuple of iterators */\r
- PyObject *result;\r
- PyObject *fillvalue = Py_None;\r
- Py_ssize_t tuplesize = PySequence_Length(args);\r
-\r
- if (kwds != NULL && PyDict_CheckExact(kwds) && PyDict_Size(kwds) > 0) {\r
- fillvalue = PyDict_GetItemString(kwds, "fillvalue");\r
- if (fillvalue == NULL || PyDict_Size(kwds) > 1) {\r
- PyErr_SetString(PyExc_TypeError,\r
- "izip_longest() got an unexpected keyword argument");\r
- return NULL;\r
- }\r
- }\r
-\r
- /* args must be a tuple */\r
- assert(PyTuple_Check(args));\r
-\r
- /* obtain iterators */\r
- ittuple = PyTuple_New(tuplesize);\r
- if (ittuple == NULL)\r
- return NULL;\r
- for (i=0; i < tuplesize; ++i) {\r
- PyObject *item = PyTuple_GET_ITEM(args, i);\r
- PyObject *it = PyObject_GetIter(item);\r
- if (it == NULL) {\r
- if (PyErr_ExceptionMatches(PyExc_TypeError))\r
- PyErr_Format(PyExc_TypeError,\r
- "izip_longest argument #%zd must support iteration",\r
- i+1);\r
- Py_DECREF(ittuple);\r
- return NULL;\r
- }\r
- PyTuple_SET_ITEM(ittuple, i, it);\r
- }\r
-\r
- /* create a result holder */\r
- result = PyTuple_New(tuplesize);\r
- if (result == NULL) {\r
- Py_DECREF(ittuple);\r
- return NULL;\r
- }\r
- for (i=0 ; i < tuplesize ; i++) {\r
- Py_INCREF(Py_None);\r
- PyTuple_SET_ITEM(result, i, Py_None);\r
- }\r
-\r
- /* create iziplongestobject structure */\r
- lz = (iziplongestobject *)type->tp_alloc(type, 0);\r
- if (lz == NULL) {\r
- Py_DECREF(ittuple);\r
- Py_DECREF(result);\r
- return NULL;\r
- }\r
- lz->ittuple = ittuple;\r
- lz->tuplesize = tuplesize;\r
- lz->numactive = tuplesize;\r
- lz->result = result;\r
- Py_INCREF(fillvalue);\r
- lz->fillvalue = fillvalue;\r
- return (PyObject *)lz;\r
-}\r
-\r
-static void\r
-izip_longest_dealloc(iziplongestobject *lz)\r
-{\r
- PyObject_GC_UnTrack(lz);\r
- Py_XDECREF(lz->ittuple);\r
- Py_XDECREF(lz->result);\r
- Py_XDECREF(lz->fillvalue);\r
- Py_TYPE(lz)->tp_free(lz);\r
-}\r
-\r
-static int\r
-izip_longest_traverse(iziplongestobject *lz, visitproc visit, void *arg)\r
-{\r
- Py_VISIT(lz->ittuple);\r
- Py_VISIT(lz->result);\r
- Py_VISIT(lz->fillvalue);\r
- return 0;\r
-}\r
-\r
-static PyObject *\r
-izip_longest_next(iziplongestobject *lz)\r
-{\r
- Py_ssize_t i;\r
- Py_ssize_t tuplesize = lz->tuplesize;\r
- PyObject *result = lz->result;\r
- PyObject *it;\r
- PyObject *item;\r
- PyObject *olditem;\r
-\r
- if (tuplesize == 0)\r
- return NULL;\r
- if (lz->numactive == 0)\r
- return NULL;\r
- if (Py_REFCNT(result) == 1) {\r
- Py_INCREF(result);\r
- for (i=0 ; i < tuplesize ; i++) {\r
- it = PyTuple_GET_ITEM(lz->ittuple, i);\r
- if (it == NULL) {\r
- Py_INCREF(lz->fillvalue);\r
- item = lz->fillvalue;\r
- } else {\r
- item = PyIter_Next(it);\r
- if (item == NULL) {\r
- lz->numactive -= 1;\r
- if (lz->numactive == 0 || PyErr_Occurred()) {\r
- lz->numactive = 0;\r
- Py_DECREF(result);\r
- return NULL;\r
- } else {\r
- Py_INCREF(lz->fillvalue);\r
- item = lz->fillvalue;\r
- PyTuple_SET_ITEM(lz->ittuple, i, NULL);\r
- Py_DECREF(it);\r
- }\r
- }\r
- }\r
- olditem = PyTuple_GET_ITEM(result, i);\r
- PyTuple_SET_ITEM(result, i, item);\r
- Py_DECREF(olditem);\r
- }\r
- } else {\r
- result = PyTuple_New(tuplesize);\r
- if (result == NULL)\r
- return NULL;\r
- for (i=0 ; i < tuplesize ; i++) {\r
- it = PyTuple_GET_ITEM(lz->ittuple, i);\r
- if (it == NULL) {\r
- Py_INCREF(lz->fillvalue);\r
- item = lz->fillvalue;\r
- } else {\r
- item = PyIter_Next(it);\r
- if (item == NULL) {\r
- lz->numactive -= 1;\r
- if (lz->numactive == 0 || PyErr_Occurred()) {\r
- lz->numactive = 0;\r
- Py_DECREF(result);\r
- return NULL;\r
- } else {\r
- Py_INCREF(lz->fillvalue);\r
- item = lz->fillvalue;\r
- PyTuple_SET_ITEM(lz->ittuple, i, NULL);\r
- Py_DECREF(it);\r
- }\r
- }\r
- }\r
- PyTuple_SET_ITEM(result, i, item);\r
- }\r
- }\r
- return result;\r
-}\r
-\r
-PyDoc_STRVAR(izip_longest_doc,\r
-"izip_longest(iter1 [,iter2 [...]], [fillvalue=None]) --> izip_longest object\n\\r
-\n\\r
-Return an izip_longest object whose .next() method returns a tuple where\n\\r
-the i-th element comes from the i-th iterable argument. The .next()\n\\r
-method continues until the longest iterable in the argument sequence\n\\r
-is exhausted and then it raises StopIteration. When the shorter iterables\n\\r
-are exhausted, the fillvalue is substituted in their place. The fillvalue\n\\r
-defaults to None or can be specified by a keyword argument.\n\\r
-");\r
-\r
-static PyTypeObject iziplongest_type = {\r
- PyVarObject_HEAD_INIT(NULL, 0)\r
- "itertools.izip_longest", /* tp_name */\r
- sizeof(iziplongestobject), /* tp_basicsize */\r
- 0, /* tp_itemsize */\r
- /* methods */\r
- (destructor)izip_longest_dealloc, /* tp_dealloc */\r
- 0, /* tp_print */\r
- 0, /* tp_getattr */\r
- 0, /* tp_setattr */\r
- 0, /* tp_compare */\r
- 0, /* tp_repr */\r
- 0, /* tp_as_number */\r
- 0, /* tp_as_sequence */\r
- 0, /* tp_as_mapping */\r
- 0, /* tp_hash */\r
- 0, /* tp_call */\r
- 0, /* tp_str */\r
- PyObject_GenericGetAttr, /* tp_getattro */\r
- 0, /* tp_setattro */\r
- 0, /* tp_as_buffer */\r
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |\r
- Py_TPFLAGS_BASETYPE, /* tp_flags */\r
- izip_longest_doc, /* tp_doc */\r
- (traverseproc)izip_longest_traverse, /* tp_traverse */\r
- 0, /* tp_clear */\r
- 0, /* tp_richcompare */\r
- 0, /* tp_weaklistoffset */\r
- PyObject_SelfIter, /* tp_iter */\r
- (iternextfunc)izip_longest_next, /* tp_iternext */\r
- 0, /* tp_methods */\r
- 0, /* tp_members */\r
- 0, /* tp_getset */\r
- 0, /* tp_base */\r
- 0, /* tp_dict */\r
- 0, /* tp_descr_get */\r
- 0, /* tp_descr_set */\r
- 0, /* tp_dictoffset */\r
- 0, /* tp_init */\r
- 0, /* tp_alloc */\r
- izip_longest_new, /* tp_new */\r
- PyObject_GC_Del, /* tp_free */\r
-};\r
-\r
-/* module level code ********************************************************/\r
-\r
-PyDoc_STRVAR(module_doc,\r
-"Functional tools for creating and using iterators.\n\\r
-\n\\r
-Infinite iterators:\n\\r
-count([n]) --> n, n+1, n+2, ...\n\\r
-cycle(p) --> p0, p1, ... plast, p0, p1, ...\n\\r
-repeat(elem [,n]) --> elem, elem, elem, ... endlessly or up to n times\n\\r
-\n\\r
-Iterators terminating on the shortest input sequence:\n\\r
-chain(p, q, ...) --> p0, p1, ... plast, q0, q1, ... \n\\r
-compress(data, selectors) --> (d[0] if s[0]), (d[1] if s[1]), ...\n\\r
-dropwhile(pred, seq) --> seq[n], seq[n+1], starting when pred fails\n\\r
-groupby(iterable[, keyfunc]) --> sub-iterators grouped by value of keyfunc(v)\n\\r
-ifilter(pred, seq) --> elements of seq where pred(elem) is True\n\\r
-ifilterfalse(pred, seq) --> elements of seq where pred(elem) is False\n\\r
-islice(seq, [start,] stop [, step]) --> elements from\n\\r
- seq[start:stop:step]\n\\r
-imap(fun, p, q, ...) --> fun(p0, q0), fun(p1, q1), ...\n\\r
-starmap(fun, seq) --> fun(*seq[0]), fun(*seq[1]), ...\n\\r
-tee(it, n=2) --> (it1, it2 , ... itn) splits one iterator into n\n\\r
-takewhile(pred, seq) --> seq[0], seq[1], until pred fails\n\\r
-izip(p, q, ...) --> (p[0], q[0]), (p[1], q[1]), ... \n\\r
-izip_longest(p, q, ...) --> (p[0], q[0]), (p[1], q[1]), ... \n\\r
-\n\\r
-Combinatoric generators:\n\\r
-product(p, q, ... [repeat=1]) --> cartesian product\n\\r
-permutations(p[, r])\n\\r
-combinations(p, r)\n\\r
-combinations_with_replacement(p, r)\n\\r
-");\r
-\r
-\r
-static PyMethodDef module_methods[] = {\r
- {"tee", (PyCFunction)tee, METH_VARARGS, tee_doc},\r
- {NULL, NULL} /* sentinel */\r
-};\r
-\r
-PyMODINIT_FUNC\r
-inititertools(void)\r
-{\r
- int i;\r
- PyObject *m;\r
- char *name;\r
- PyTypeObject *typelist[] = {\r
- &combinations_type,\r
- &cwr_type,\r
- &cycle_type,\r
- &dropwhile_type,\r
- &takewhile_type,\r
- &islice_type,\r
- &starmap_type,\r
- &imap_type,\r
- &chain_type,\r
- &compress_type,\r
- &ifilter_type,\r
- &ifilterfalse_type,\r
- &count_type,\r
- &izip_type,\r
- &iziplongest_type,\r
- &permutations_type,\r
- &product_type,\r
- &repeat_type,\r
- &groupby_type,\r
- NULL\r
- };\r
-\r
- Py_TYPE(&teedataobject_type) = &PyType_Type;\r
- m = Py_InitModule3("itertools", module_methods, module_doc);\r
- if (m == NULL)\r
- return;\r
-\r
- for (i=0 ; typelist[i] != NULL ; i++) {\r
- if (PyType_Ready(typelist[i]) < 0)\r
- return;\r
- name = strchr(typelist[i]->tp_name, '.');\r
- assert (name != NULL);\r
- Py_INCREF(typelist[i]);\r
- PyModule_AddObject(m, name+1, (PyObject *)typelist[i]);\r
- }\r
-\r
- if (PyType_Ready(&teedataobject_type) < 0)\r
- return;\r
- if (PyType_Ready(&tee_type) < 0)\r
- return;\r
- if (PyType_Ready(&_grouper_type) < 0)\r
- return;\r
-}\r