static PyObject * range_iter(PyObject *seq) { rangeobject *r = (rangeobject *)seq; longrangeiterobject *it; long lstart, lstop, lstep; PyObject *int_it; assert(PyRange_Check(seq)); /* If all three fields and the length convert to long, use the int * version */ lstart = PyLong_AsLong(r->start); if (lstart == -1 && PyErr_Occurred()) { PyErr_Clear(); goto long_range; } lstop = PyLong_AsLong(r->stop); if (lstop == -1 && PyErr_Occurred()) { PyErr_Clear(); goto long_range; } lstep = PyLong_AsLong(r->step); if (lstep == -1 && PyErr_Occurred()) { PyErr_Clear(); goto long_range; } int_it = fast_range_iter(lstart, lstop, lstep); if (int_it == NULL && PyErr_ExceptionMatches(PyExc_OverflowError)) { PyErr_Clear(); goto long_range; } return (PyObject *)int_it; long_range: it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type); if (it == NULL) return NULL; /* Do all initialization here, so we can DECREF on failure. */ it->start = r->start; it->step = r->step; it->len = r->length; Py_INCREF(it->start); Py_INCREF(it->step); Py_INCREF(it->len); it->index = PyLong_FromLong(0); if (!it->index) goto create_failure; return (PyObject *)it; create_failure: Py_DECREF(it); return NULL; }
static PyObject * rangeiter_new(PyTypeObject *type, PyObject *args, PyObject *kw) { long start, stop, step; if (!_PyArg_NoKeywords("rangeiter()", kw)) return NULL; if (!PyArg_ParseTuple(args, "lll;rangeiter() requires 3 int arguments", &start, &stop, &step)) return NULL; return fast_range_iter(start, stop, step); }
static PyObject * range_iter(PyObject *seq) { rangeobject *r = (rangeobject *)seq; longrangeiterobject *it; long lstart, lstop, lstep; PyObject *int_it; assert(PyRange_Check(seq)); /* If all three fields and the length convert to long, use the int * version */ lstart = PyLong_AsLong(r->start); if (lstart == -1 && PyErr_Occurred()) { PyErr_Clear(); goto long_range; } lstop = PyLong_AsLong(r->stop); if (lstop == -1 && PyErr_Occurred()) { PyErr_Clear(); goto long_range; } lstep = PyLong_AsLong(r->step); if (lstep == -1 && PyErr_Occurred()) { PyErr_Clear(); goto long_range; } int_it = fast_range_iter(lstart, lstop, lstep); if (int_it == NULL && PyErr_ExceptionMatches(PyExc_OverflowError)) { PyErr_Clear(); goto long_range; } return (PyObject *)int_it; long_range: it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type); if (it == NULL) return NULL; it->start = r->start; it->step = r->step; it->len = r->length; it->index = _PyLong_Zero; Py_INCREF(it->start); Py_INCREF(it->step); Py_INCREF(it->len); Py_INCREF(it->index); return (PyObject *)it; }
static PyObject * range_reverse(PyObject *seq) { rangeobject *range = (rangeobject*) seq; longrangeiterobject *it; PyObject *one, *sum, *diff, *product; long lstart, lstop, lstep, new_start, new_stop; unsigned long ulen; assert(PyRange_Check(seq)); /* reversed(range(start, stop, step)) can be expressed as range(start+(n-1)*step, start-step, -step), where n is the number of integers in the range. If each of start, stop, step, -step, start-step, and the length of the iterator is representable as a C long, use the int version. This excludes some cases where the reversed range is representable as a range_iterator, but it's good enough for common cases and it makes the checks simple. */ lstart = PyLong_AsLong(range->start); if (lstart == -1 && PyErr_Occurred()) { PyErr_Clear(); goto long_range; } lstop = PyLong_AsLong(range->stop); if (lstop == -1 && PyErr_Occurred()) { PyErr_Clear(); goto long_range; } lstep = PyLong_AsLong(range->step); if (lstep == -1 && PyErr_Occurred()) { PyErr_Clear(); goto long_range; } /* check for possible overflow of -lstep */ if (lstep == LONG_MIN) goto long_range; /* check for overflow of lstart - lstep: for lstep > 0, need only check whether lstart - lstep < LONG_MIN. for lstep < 0, need only check whether lstart - lstep > LONG_MAX Rearrange these inequalities as: lstart - LONG_MIN < lstep (lstep > 0) LONG_MAX - lstart < -lstep (lstep < 0) and compute both sides as unsigned longs, to avoid the possibility of undefined behaviour due to signed overflow. */ if (lstep > 0) { if ((unsigned long)lstart - LONG_MIN < (unsigned long)lstep) goto long_range; } else { if (LONG_MAX - (unsigned long)lstart < 0UL - lstep) goto long_range; } ulen = get_len_of_range(lstart, lstop, lstep); if (ulen > (unsigned long)LONG_MAX) goto long_range; new_stop = lstart - lstep; new_start = (long)(new_stop + ulen * lstep); return fast_range_iter(new_start, new_stop, -lstep); long_range: it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type); if (it == NULL) return NULL; /* start + (len - 1) * step */ it->len = range->length; Py_INCREF(it->len); one = PyLong_FromLong(1); if (!one) goto create_failure; diff = PyNumber_Subtract(it->len, one); Py_DECREF(one); if (!diff) goto create_failure; product = PyNumber_Multiply(diff, range->step); Py_DECREF(diff); if (!product) goto create_failure; sum = PyNumber_Add(range->start, product); Py_DECREF(product); it->start = sum; if (!it->start) goto create_failure; it->step = PyNumber_Negative(range->step); if (!it->step) goto create_failure; it->index = PyLong_FromLong(0); if (!it->index) goto create_failure; return (PyObject *)it; create_failure: Py_DECREF(it); return NULL; }