static PyObject * range_richcompare(PyObject *self, PyObject *other, int op) { int result; if (!PyRange_Check(other)) Py_RETURN_NOTIMPLEMENTED; switch (op) { case Py_NE: case Py_EQ: result = range_equals((rangeobject*)self, (rangeobject*)other); if (result == -1) return NULL; if (op == Py_NE) result = !result; if (result) Py_RETURN_TRUE; else Py_RETURN_FALSE; case Py_LE: case Py_GE: case Py_LT: case Py_GT: Py_RETURN_NOTIMPLEMENTED; default: PyErr_BadArgument(); return NULL; } }
static PyObject * range_reverse(PyObject *seq) { rangeiterobject *it; long start, step, len; if (!PyRange_Check(seq)) { PyErr_BadInternalCall(); return NULL; } it = PyObject_New(rangeiterobject, &Pyrangeiter_Type); if (it == NULL) return NULL; start = ((rangeobject *)seq)->start; step = ((rangeobject *)seq)->step; len = ((rangeobject *)seq)->len; it->index = 0; it->start = start + (len-1) * step; it->step = -step; it->len = len; return (PyObject *)it; }
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 * 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_iter(PyObject *seq) { rangeiterobject *it; if (!PyRange_Check(seq)) { PyErr_BadInternalCall(); return NULL; } it = PyObject_New(rangeiterobject, &Pyrangeiter_Type); if (it == NULL) return NULL; it->index = 0; it->start = ((rangeobject *)seq)->start; it->step = ((rangeobject *)seq)->step; it->len = ((rangeobject *)seq)->len; 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; }
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; }