summaryrefslogtreecommitdiffstats
path: root/Modules/itertoolsmodule.c
diff options
context:
space:
mode:
Diffstat (limited to 'Modules/itertoolsmodule.c')
-rw-r--r--Modules/itertoolsmodule.c71
1 files changed, 62 insertions, 9 deletions
diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c
index b030c12..8e5b3d0 100644
--- a/Modules/itertoolsmodule.c
+++ b/Modules/itertoolsmodule.c
@@ -2032,6 +2032,7 @@ static PyTypeObject ifilterfalse_type = {
typedef struct {
PyObject_HEAD
Py_ssize_t cnt;
+ PyObject *long_cnt; /* Arbitrarily large count when cnt >= PY_SSIZE_T_MAX */
} countobject;
static PyTypeObject count_type;
@@ -2041,37 +2042,89 @@ count_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
countobject *lz;
Py_ssize_t cnt = 0;
+ PyObject *cnt_arg = NULL;
+ PyObject *long_cnt = NULL;
if (type == &count_type && !_PyArg_NoKeywords("count()", kwds))
return NULL;
- if (!PyArg_ParseTuple(args, "|n:count", &cnt))
+ if (!PyArg_UnpackTuple(args, "count", 0, 1, &cnt_arg))
return NULL;
+ if (cnt_arg != NULL) {
+ cnt = PyInt_AsSsize_t(cnt_arg);
+ if (cnt == -1 && PyErr_Occurred()) {
+ PyErr_Clear();
+ if (!PyLong_Check(cnt_arg)) {
+ PyErr_SetString(PyExc_TypeError, "an integer is required");
+ return NULL;
+ }
+ long_cnt = cnt_arg;
+ Py_INCREF(long_cnt);
+ cnt = PY_SSIZE_T_MAX;
+ }
+ }
+
/* create countobject structure */
lz = (countobject *)PyObject_New(countobject, &count_type);
- if (lz == NULL)
+ if (lz == NULL) {
+ Py_XDECREF(long_cnt);
return NULL;
+ }
lz->cnt = cnt;
+ lz->long_cnt = long_cnt;
return (PyObject *)lz;
}
+static void
+count_dealloc(countobject *lz)
+{
+ Py_XDECREF(lz->long_cnt);
+ PyObject_Del(lz);
+}
+
+static PyObject *
+count_nextlong(countobject *lz)
+{
+ static PyObject *one = NULL;
+ PyObject *cnt;
+ PyObject *stepped_up;
+
+ if (lz->long_cnt == NULL) {
+ lz->long_cnt = PyInt_FromSsize_t(PY_SSIZE_T_MAX);
+ if (lz->long_cnt == NULL)
+ return NULL;
+ }
+ if (one == NULL) {
+ one = PyInt_FromLong(1);
+ if (one == NULL)
+ return NULL;
+ }
+ cnt = lz->long_cnt;
+ assert(cnt != NULL);
+ stepped_up = PyNumber_Add(cnt, one);
+ if (stepped_up == NULL)
+ return NULL;
+ lz->long_cnt = stepped_up;
+ return cnt;
+}
+
static PyObject *
count_next(countobject *lz)
{
- if (lz->cnt == PY_SSIZE_T_MAX) {
- PyErr_SetString(PyExc_OverflowError,
- "cannot count beyond PY_SSIZE_T_MAX");
- return NULL;
- }
+ if (lz->cnt == PY_SSIZE_T_MAX)
+ return count_nextlong(lz);
return PyInt_FromSsize_t(lz->cnt++);
}
static PyObject *
count_repr(countobject *lz)
{
- return PyUnicode_FromFormat("count(%zd)", lz->cnt);
+ if (lz->cnt != PY_SSIZE_T_MAX)
+ return PyUnicode_FromFormat("count(%zd)", lz->cnt);
+
+ return PyUnicode_FromFormat("count(%R)", lz->long_cnt);
}
PyDoc_STRVAR(count_doc,
@@ -2086,7 +2139,7 @@ static PyTypeObject count_type = {
sizeof(countobject), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
- (destructor)PyObject_Del, /* tp_dealloc */
+ (destructor)count_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */