diff -r 8a5bebea9fec Modules/itertoolsmodule.c --- a/Modules/itertoolsmodule.c Wed May 08 13:23:25 2013 +0200 +++ b/Modules/itertoolsmodule.c Wed May 08 18:39:25 2013 +0300 @@ -4446,6 +4446,166 @@ PyObject_GC_Del, /* tp_free */ }; +/* chunks object ************************************************************/ + +typedef struct { + PyObject_HEAD + PyObject *seq; + Py_ssize_t size; + Py_ssize_t index; +} chunksobject; + +static PyTypeObject chunks_type; + +static PyObject * +chunks_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyObject *seq; + Py_ssize_t size, start = 0; + chunksobject *co; + static char *kwargs[] = {"seq", "size", "start", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "On|n:chunks", kwargs, + &seq, &size, &start)) + return NULL; + + if (size <= 0) { + PyErr_Format(PyExc_ValueError, "size must be > 0"); + return NULL; + } + + if (start < 0) { + PyErr_Format(PyExc_ValueError, "start must be >= 0"); + return NULL; + } + + /* create chunksobject structure */ + co = (chunksobject *)type->tp_alloc(type, 0); + if (co == NULL) { + Py_DECREF(seq); + return NULL; + } + Py_INCREF(seq); + co->seq = seq; + co->size = size; + co->index = start; + + return (PyObject *)co; +} + +static void +chunks_dealloc(chunksobject *co) +{ + PyObject_GC_UnTrack(co); + Py_XDECREF(co->seq); + Py_TYPE(co)->tp_free(co); +} + +static int +chunks_traverse(chunksobject *co, visitproc visit, void *arg) +{ + Py_VISIT(co->seq); + return 0; +} + +static PyObject * +chunks_next(chunksobject *co) +{ + PyObject *chunk; + Py_ssize_t next, size; + + if (co->index > PY_SIZE_MAX - co->size) + next = PY_SIZE_MAX; + else + next = co->index + co->size; + + chunk = PySequence_GetSlice(co->seq, co->index, next); + if (chunk == NULL) + return NULL; + + size = PySequence_Size(chunk); + if (size <= 0) { + /* an error or end of iteration */ + Py_DECREF(chunk); + return NULL; + } + + co->index = next; + return chunk; +} + +static PyObject * +chunks_len(chunksobject *co) +{ + Py_ssize_t size = PySequence_Size(co->seq); + if (size == -1 && PyErr_Occurred()) + return NULL; + return PyLong_FromSize_t(size / co->size); +} + +static PyObject * +chunks_reduce(chunksobject *co) +{ + return Py_BuildValue("O(Onn)", Py_TYPE(co), + co->seq, co->size, co->index); +} + +static PyMethodDef chunks_methods[] = { + {"__length_hint__", (PyCFunction)chunks_len, METH_NOARGS, length_hint_doc}, + {"__reduce__", (PyCFunction)chunks_reduce, METH_NOARGS, reduce_doc}, + {NULL, NULL} /* sentinel */ +}; + +PyDoc_STRVAR(chunks_doc, +"chunks(sequence, size, [start]) --> chunks iterator\n\ +\n\ +Split a sequence on chunks of specified size:\n\ +sequence[start: start + size], sequence[start + size: start + 2*size],.."); + +static PyTypeObject chunks_type = { + PyVarObject_HEAD_INIT(NULL, 0) + "itertools.chunks", /* tp_name */ + sizeof(chunksobject), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)chunks_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_BASETYPE, /* tp_flags */ + chunks_doc, /* tp_doc */ + (traverseproc)chunks_traverse, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + PyObject_SelfIter, /* tp_iter */ + (iternextfunc)chunks_next, /* tp_iternext */ + chunks_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + chunks_new, /* tp_new */ + PyObject_GC_Del, /* tp_free */ +}; + /* module level code ********************************************************/ PyDoc_STRVAR(module_doc, @@ -4523,6 +4683,7 @@ &_grouper_type, &tee_type, &teedataobject_type, + &chunks_type, NULL }; @@ -4542,3 +4703,6 @@ return m; } + + +