summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorRaymond Hettinger <python@rcn.com>2007-10-03 21:18:11 (GMT)
committerRaymond Hettinger <python@rcn.com>2007-10-03 21:18:11 (GMT)
commit8f6693701c1899168f5bca96549ae2f2f590624e (patch)
tree1d2a60b9e8d754b3c0ada701a3e075d15f4c09c1 /Objects
parentd92e871ad8b71de1a276f94d14b797e2e049ced8 (diff)
downloadcpython-8f6693701c1899168f5bca96549ae2f2f590624e.zip
cpython-8f6693701c1899168f5bca96549ae2f2f590624e.tar.gz
cpython-8f6693701c1899168f5bca96549ae2f2f590624e.tar.bz2
enumerate() is no longer bounded to using sequences shorter than LONG_MAX. The possibility of overflow was sending some newsgroup posters into a tizzy.
Diffstat (limited to 'Objects')
-rw-r--r--Objects/enumobject.c55
1 files changed, 49 insertions, 6 deletions
diff --git a/Objects/enumobject.c b/Objects/enumobject.c
index 6997fdc..0a3694d 100644
--- a/Objects/enumobject.c
+++ b/Objects/enumobject.c
@@ -7,6 +7,7 @@ typedef struct {
long en_index; /* current index of enumeration */
PyObject* en_sit; /* secondary iterator of enumeration */
PyObject* en_result; /* result tuple */
+ PyObject* en_longindex; /* index for sequences >= LONG_MAX */
} enumobject;
static PyObject *
@@ -25,6 +26,7 @@ enum_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return NULL;
en->en_index = 0;
en->en_sit = PyObject_GetIter(seq);
+ en->en_longindex = NULL;
if (en->en_sit == NULL) {
Py_DECREF(en);
return NULL;
@@ -43,6 +45,7 @@ enum_dealloc(enumobject *en)
PyObject_GC_UnTrack(en);
Py_XDECREF(en->en_sit);
Py_XDECREF(en->en_result);
+ Py_XDECREF(en->en_longindex);
Py_Type(en)->tp_free(en);
}
@@ -51,10 +54,53 @@ enum_traverse(enumobject *en, visitproc visit, void *arg)
{
Py_VISIT(en->en_sit);
Py_VISIT(en->en_result);
+ Py_VISIT(en->en_longindex);
return 0;
}
static PyObject *
+enum_next_long(enumobject *en, PyObject* next_item)
+{
+ static PyObject *one = NULL;
+ PyObject *result = en->en_result;
+ PyObject *next_index;
+ PyObject *stepped_up;
+
+ if (en->en_longindex == NULL) {
+ en->en_longindex = PyInt_FromLong(LONG_MAX);
+ if (en->en_longindex == NULL)
+ return NULL;
+ }
+ if (one == NULL) {
+ one = PyInt_FromLong(1);
+ if (one == NULL)
+ return NULL;
+ }
+ next_index = en->en_longindex;
+ assert(next_index != NULL);
+ stepped_up = PyNumber_Add(next_index, one);
+ if (stepped_up == NULL)
+ return NULL;
+ en->en_longindex = stepped_up;
+
+ if (result->ob_refcnt == 1) {
+ Py_INCREF(result);
+ Py_DECREF(PyTuple_GET_ITEM(result, 0));
+ Py_DECREF(PyTuple_GET_ITEM(result, 1));
+ } else {
+ result = PyTuple_New(2);
+ if (result == NULL) {
+ Py_DECREF(next_index);
+ Py_DECREF(next_item);
+ return NULL;
+ }
+ }
+ PyTuple_SET_ITEM(result, 0, next_index);
+ PyTuple_SET_ITEM(result, 1, next_item);
+ return result;
+}
+
+static PyObject *
enum_next(enumobject *en)
{
PyObject *next_index;
@@ -62,16 +108,13 @@ enum_next(enumobject *en)
PyObject *result = en->en_result;
PyObject *it = en->en_sit;
- if (en->en_index == LONG_MAX) {
- PyErr_SetString(PyExc_OverflowError,
- "enumerate() is limited to LONG_MAX items");
- return NULL;
- }
-
next_item = (*Py_Type(it)->tp_iternext)(it);
if (next_item == NULL)
return NULL;
+ if (en->en_index == LONG_MAX)
+ return enum_next_long(en, next_item);
+
next_index = PyInt_FromLong(en->en_index);
if (next_index == NULL) {
Py_DECREF(next_item);