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 = int_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; Py_INCREF(it->start); Py_INCREF(it->step); it->len = it->index = NULL; it->len = range_length_obj(r); if (!it->len) goto create_failure; it->index = PyLong_FromLong(0); if (!it->index) goto create_failure; return (PyObject *)it; create_failure: Py_DECREF(it); return NULL; }
static PyObject * range_iter(PyObject *seq) { rangeobject *r = (rangeobject *)seq; longrangeiterobject *it; PyObject *tmp, *len; long lstart, lstop, lstep; assert(PyRange_Check(seq)); /* If all three fields convert to long, use the int version */ lstart = PyLong_AsLong(r->start); if (lstart != -1 || !PyErr_Occurred()) { lstop = PyLong_AsLong(r->stop); if (lstop != -1 || !PyErr_Occurred()) { lstep = PyLong_AsLong(r->step); if (lstep != -1 || !PyErr_Occurred()) return int_range_iter(lstart, lstop, lstep); } } /* Some conversion failed, so there is an error set. Clear it, and try again with a long range. */ PyErr_Clear(); 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; Py_INCREF(it->start); Py_INCREF(it->step); it->len = it->index = NULL; /* Calculate length: (r->stop - r->start) / r->step */ tmp = PyNumber_Subtract(r->stop, r->start); if (!tmp) goto create_failure; len = PyNumber_FloorDivide(tmp, r->step); Py_DECREF(tmp); if (!len) goto create_failure; it->len = 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 int_range_iter(start, stop, step); }
static PyObject * range_reverse(PyObject *seq) { rangeobject *range = (rangeobject*) seq; longrangeiterobject *it; PyObject *one, *sum, *diff, *len = NULL, *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 int_range_iter(new_start, new_stop, -lstep); long_range: it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type); if (it == NULL) return NULL; /* start + (len - 1) * step */ len = range_length_obj(range); if (!len) goto create_failure; /* Steal reference to len. */ it->len = len; one = PyLong_FromLong(1); if (!one) goto create_failure; diff = PyNumber_Subtract(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; }
static PyObject * range_reverse(PyObject *seq) { rangeobject *range = (rangeobject*) seq; longrangeiterobject *it; PyObject *one, *sum, *diff, *len = NULL, *product; long lstart, lstop, lstep; /* XXX(nnorwitz): do the calc for the new start/stop first, then if they fit, call the proper iter()? */ assert(PyRange_Check(seq)); /* If all three fields convert to long, use the int version */ lstart = PyLong_AsLong(range->start); if (lstart != -1 || !PyErr_Occurred()) { lstop = PyLong_AsLong(range->stop); if (lstop != -1 || !PyErr_Occurred()) { lstep = PyLong_AsLong(range->step); if (lstep != -1 || !PyErr_Occurred()) { /* XXX(nnorwitz): need to check for overflow and simplify. */ long len = get_len_of_range(lstart, lstop, lstep); long new_start = lstart + (len - 1) * lstep; long new_stop = lstart; if (lstep > 0) new_stop -= 1; else new_stop += 1; return int_range_iter(new_start, new_stop, -lstep); } } } PyErr_Clear(); it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type); if (it == NULL) return NULL; /* start + (len - 1) * step */ len = range_length_obj(range); if (!len) goto create_failure; one = PyLong_FromLong(1); if (!one) goto create_failure; diff = PyNumber_Subtract(len, one); Py_DECREF(one); if (!diff) goto create_failure; product = PyNumber_Multiply(len, range->step); 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) { Py_DECREF(it->start); PyObject_Del(it); return NULL; } /* Steal reference to len. */ it->len = len; it->index = PyLong_FromLong(0); if (!it->index) { Py_DECREF(it); return NULL; } return (PyObject *)it; create_failure: Py_XDECREF(len); PyObject_Del(it); return NULL; }