• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Range object implementation */
2 
3 #include "Python.h"
4 #include "pycore_abstract.h"      // _PyIndex_Check()
5 #include "pycore_ceval.h"         // _PyEval_GetBuiltin()
6 #include "pycore_long.h"          // _PyLong_GetZero()
7 #include "pycore_modsupport.h"    // _PyArg_NoKwnames()
8 #include "pycore_range.h"
9 #include "pycore_tuple.h"         // _PyTuple_ITEMS()
10 
11 
12 /* Support objects whose length is > PY_SSIZE_T_MAX.
13 
14    This could be sped up for small PyLongs if they fit in a Py_ssize_t.
15    This only matters on Win64.  Though we could use long long which
16    would presumably help perf.
17 */
18 
19 typedef struct {
20     PyObject_HEAD
21     PyObject *start;
22     PyObject *stop;
23     PyObject *step;
24     PyObject *length;
25 } rangeobject;
26 
27 /* Helper function for validating step.  Always returns a new reference or
28    NULL on error.
29 */
30 static PyObject *
validate_step(PyObject * step)31 validate_step(PyObject *step)
32 {
33     /* No step specified, use a step of 1. */
34     if (!step)
35         return PyLong_FromLong(1);
36 
37     step = PyNumber_Index(step);
38     if (step && _PyLong_IsZero((PyLongObject *)step)) {
39         PyErr_SetString(PyExc_ValueError,
40                         "range() arg 3 must not be zero");
41         Py_CLEAR(step);
42     }
43 
44     return step;
45 }
46 
47 static PyObject *
48 compute_range_length(PyObject *start, PyObject *stop, PyObject *step);
49 
50 static rangeobject *
make_range_object(PyTypeObject * type,PyObject * start,PyObject * stop,PyObject * step)51 make_range_object(PyTypeObject *type, PyObject *start,
52                   PyObject *stop, PyObject *step)
53 {
54     rangeobject *obj = NULL;
55     PyObject *length;
56     length = compute_range_length(start, stop, step);
57     if (length == NULL) {
58         return NULL;
59     }
60     obj = PyObject_New(rangeobject, type);
61     if (obj == NULL) {
62         Py_DECREF(length);
63         return NULL;
64     }
65     obj->start = start;
66     obj->stop = stop;
67     obj->step = step;
68     obj->length = length;
69     return obj;
70 }
71 
72 /* XXX(nnorwitz): should we error check if the user passes any empty ranges?
73    range(-10)
74    range(0, -5)
75    range(0, 5, -1)
76 */
77 static PyObject *
range_from_array(PyTypeObject * type,PyObject * const * args,Py_ssize_t num_args)78 range_from_array(PyTypeObject *type, PyObject *const *args, Py_ssize_t num_args)
79 {
80     rangeobject *obj;
81     PyObject *start = NULL, *stop = NULL, *step = NULL;
82 
83     switch (num_args) {
84         case 3:
85             step = args[2];
86             /* fallthrough */
87         case 2:
88             /* Convert borrowed refs to owned refs */
89             start = PyNumber_Index(args[0]);
90             if (!start) {
91                 return NULL;
92             }
93             stop = PyNumber_Index(args[1]);
94             if (!stop) {
95                 Py_DECREF(start);
96                 return NULL;
97             }
98             step = validate_step(step);  /* Caution, this can clear exceptions */
99             if (!step) {
100                 Py_DECREF(start);
101                 Py_DECREF(stop);
102                 return NULL;
103             }
104             break;
105         case 1:
106             stop = PyNumber_Index(args[0]);
107             if (!stop) {
108                 return NULL;
109             }
110             start = _PyLong_GetZero();
111             step = _PyLong_GetOne();
112             break;
113         case 0:
114             PyErr_SetString(PyExc_TypeError,
115                             "range expected at least 1 argument, got 0");
116             return NULL;
117         default:
118             PyErr_Format(PyExc_TypeError,
119                          "range expected at most 3 arguments, got %zd",
120                          num_args);
121             return NULL;
122     }
123     obj = make_range_object(type, start, stop, step);
124     if (obj != NULL) {
125         return (PyObject *) obj;
126     }
127 
128     /* Failed to create object, release attributes */
129     Py_DECREF(start);
130     Py_DECREF(stop);
131     Py_DECREF(step);
132     return NULL;
133 }
134 
135 static PyObject *
range_new(PyTypeObject * type,PyObject * args,PyObject * kw)136 range_new(PyTypeObject *type, PyObject *args, PyObject *kw)
137 {
138     if (!_PyArg_NoKeywords("range", kw))
139         return NULL;
140 
141     return range_from_array(type, _PyTuple_ITEMS(args), PyTuple_GET_SIZE(args));
142 }
143 
144 
145 static PyObject *
range_vectorcall(PyTypeObject * type,PyObject * const * args,size_t nargsf,PyObject * kwnames)146 range_vectorcall(PyTypeObject *type, PyObject *const *args,
147                  size_t nargsf, PyObject *kwnames)
148 {
149     Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
150     if (!_PyArg_NoKwnames("range", kwnames)) {
151         return NULL;
152     }
153     return range_from_array(type, args, nargs);
154 }
155 
156 PyDoc_STRVAR(range_doc,
157 "range(stop) -> range object\n\
158 range(start, stop[, step]) -> range object\n\
159 \n\
160 Return an object that produces a sequence of integers from start (inclusive)\n\
161 to stop (exclusive) by step.  range(i, j) produces i, i+1, i+2, ..., j-1.\n\
162 start defaults to 0, and stop is omitted!  range(4) produces 0, 1, 2, 3.\n\
163 These are exactly the valid indices for a list of 4 elements.\n\
164 When step is given, it specifies the increment (or decrement).");
165 
166 static void
range_dealloc(rangeobject * r)167 range_dealloc(rangeobject *r)
168 {
169     Py_DECREF(r->start);
170     Py_DECREF(r->stop);
171     Py_DECREF(r->step);
172     Py_DECREF(r->length);
173     PyObject_Free(r);
174 }
175 
176 static unsigned long
177 get_len_of_range(long lo, long hi, long step);
178 
179 /* Return the length as a long, -2 for an overflow and -1 for any other type of error
180  *
181  * In case of an overflow no error is set
182  */
compute_range_length_long(PyObject * start,PyObject * stop,PyObject * step)183 static long compute_range_length_long(PyObject *start,
184                 PyObject *stop, PyObject *step) {
185     int overflow = 0;
186 
187     long long_start = PyLong_AsLongAndOverflow(start, &overflow);
188     if (overflow) {
189         return -2;
190     }
191     if (long_start == -1 && PyErr_Occurred()) {
192         return -1;
193     }
194     long long_stop = PyLong_AsLongAndOverflow(stop, &overflow);
195     if (overflow) {
196         return -2;
197     }
198     if (long_stop == -1 && PyErr_Occurred()) {
199         return -1;
200     }
201     long long_step = PyLong_AsLongAndOverflow(step, &overflow);
202     if (overflow) {
203         return -2;
204     }
205     if (long_step == -1 && PyErr_Occurred()) {
206         return -1;
207     }
208 
209     unsigned long ulen = get_len_of_range(long_start, long_stop, long_step);
210     if (ulen > (unsigned long)LONG_MAX) {
211         /* length too large for a long */
212         return -2;
213     }
214     else {
215         return (long)ulen;
216     }
217 }
218 
219 /* Return number of items in range (lo, hi, step) as a PyLong object,
220  * when arguments are PyLong objects.  Arguments MUST return 1 with
221  * PyLong_Check().  Return NULL when there is an error.
222  */
223 static PyObject*
compute_range_length(PyObject * start,PyObject * stop,PyObject * step)224 compute_range_length(PyObject *start, PyObject *stop, PyObject *step)
225 {
226     /* -------------------------------------------------------------
227     Algorithm is equal to that of get_len_of_range(), but it operates
228     on PyObjects (which are assumed to be PyLong objects).
229     ---------------------------------------------------------------*/
230     int cmp_result;
231     PyObject *lo, *hi;
232     PyObject *diff = NULL;
233     PyObject *tmp1 = NULL, *tmp2 = NULL, *result;
234                 /* holds sub-expression evaluations */
235 
236     PyObject *zero = _PyLong_GetZero();  // borrowed reference
237     PyObject *one = _PyLong_GetOne();  // borrowed reference
238 
239     assert(PyLong_Check(start));
240     assert(PyLong_Check(stop));
241     assert(PyLong_Check(step));
242 
243     /* fast path when all arguments fit into a long integer */
244     long len = compute_range_length_long(start, stop, step);
245     if (len >= 0) {
246         return PyLong_FromLong(len);
247     }
248     else if (len == -1) {
249         /* unexpected error from compute_range_length_long, we propagate to the caller */
250         return NULL;
251     }
252     assert(len == -2);
253 
254     cmp_result = PyObject_RichCompareBool(step, zero, Py_GT);
255     if (cmp_result == -1)
256         return NULL;
257 
258     if (cmp_result == 1) {
259         lo = start;
260         hi = stop;
261         Py_INCREF(step);
262     } else {
263         lo = stop;
264         hi = start;
265         step = PyNumber_Negative(step);
266         if (!step)
267             return NULL;
268     }
269 
270     /* if (lo >= hi), return length of 0. */
271     cmp_result = PyObject_RichCompareBool(lo, hi, Py_GE);
272     if (cmp_result != 0) {
273         Py_DECREF(step);
274         if (cmp_result < 0)
275             return NULL;
276         result = zero;
277         return Py_NewRef(result);
278     }
279 
280     if ((tmp1 = PyNumber_Subtract(hi, lo)) == NULL)
281         goto Fail;
282 
283     if ((diff = PyNumber_Subtract(tmp1, one)) == NULL)
284         goto Fail;
285 
286     if ((tmp2 = PyNumber_FloorDivide(diff, step)) == NULL)
287         goto Fail;
288 
289     if ((result = PyNumber_Add(tmp2, one)) == NULL)
290         goto Fail;
291 
292     Py_DECREF(tmp2);
293     Py_DECREF(diff);
294     Py_DECREF(step);
295     Py_DECREF(tmp1);
296     return result;
297 
298   Fail:
299     Py_DECREF(step);
300     Py_XDECREF(tmp2);
301     Py_XDECREF(diff);
302     Py_XDECREF(tmp1);
303     return NULL;
304 }
305 
306 static Py_ssize_t
range_length(rangeobject * r)307 range_length(rangeobject *r)
308 {
309     return PyLong_AsSsize_t(r->length);
310 }
311 
312 static PyObject *
compute_item(rangeobject * r,PyObject * i)313 compute_item(rangeobject *r, PyObject *i)
314 {
315     PyObject *incr, *result;
316     /* PyLong equivalent to:
317      *    return r->start + (i * r->step)
318      */
319     if (r->step == _PyLong_GetOne()) {
320         result = PyNumber_Add(r->start, i);
321     }
322     else {
323         incr = PyNumber_Multiply(i, r->step);
324         if (!incr) {
325             return NULL;
326         }
327         result = PyNumber_Add(r->start, incr);
328         Py_DECREF(incr);
329     }
330     return result;
331 }
332 
333 static PyObject *
compute_range_item(rangeobject * r,PyObject * arg)334 compute_range_item(rangeobject *r, PyObject *arg)
335 {
336     PyObject *zero = _PyLong_GetZero();  // borrowed reference
337     int cmp_result;
338     PyObject *i, *result;
339 
340     /* PyLong equivalent to:
341      *   if (arg < 0) {
342      *     i = r->length + arg
343      *   } else {
344      *     i = arg
345      *   }
346      */
347     cmp_result = PyObject_RichCompareBool(arg, zero, Py_LT);
348     if (cmp_result == -1) {
349         return NULL;
350     }
351     if (cmp_result == 1) {
352         i = PyNumber_Add(r->length, arg);
353         if (!i) {
354           return NULL;
355         }
356     } else {
357         i = Py_NewRef(arg);
358     }
359 
360     /* PyLong equivalent to:
361      *   if (i < 0 || i >= r->length) {
362      *     <report index out of bounds>
363      *   }
364      */
365     cmp_result = PyObject_RichCompareBool(i, zero, Py_LT);
366     if (cmp_result == 0) {
367         cmp_result = PyObject_RichCompareBool(i, r->length, Py_GE);
368     }
369     if (cmp_result == -1) {
370        Py_DECREF(i);
371        return NULL;
372     }
373     if (cmp_result == 1) {
374         Py_DECREF(i);
375         PyErr_SetString(PyExc_IndexError,
376                         "range object index out of range");
377         return NULL;
378     }
379 
380     result = compute_item(r, i);
381     Py_DECREF(i);
382     return result;
383 }
384 
385 static PyObject *
range_item(rangeobject * r,Py_ssize_t i)386 range_item(rangeobject *r, Py_ssize_t i)
387 {
388     PyObject *res, *arg = PyLong_FromSsize_t(i);
389     if (!arg) {
390         return NULL;
391     }
392     res = compute_range_item(r, arg);
393     Py_DECREF(arg);
394     return res;
395 }
396 
397 static PyObject *
compute_slice(rangeobject * r,PyObject * _slice)398 compute_slice(rangeobject *r, PyObject *_slice)
399 {
400     PySliceObject *slice = (PySliceObject *) _slice;
401     rangeobject *result;
402     PyObject *start = NULL, *stop = NULL, *step = NULL;
403     PyObject *substart = NULL, *substop = NULL, *substep = NULL;
404     int error;
405 
406     error = _PySlice_GetLongIndices(slice, r->length, &start, &stop, &step);
407     if (error == -1)
408         return NULL;
409 
410     substep = PyNumber_Multiply(r->step, step);
411     if (substep == NULL) goto fail;
412     Py_CLEAR(step);
413 
414     substart = compute_item(r, start);
415     if (substart == NULL) goto fail;
416     Py_CLEAR(start);
417 
418     substop = compute_item(r, stop);
419     if (substop == NULL) goto fail;
420     Py_CLEAR(stop);
421 
422     result = make_range_object(Py_TYPE(r), substart, substop, substep);
423     if (result != NULL) {
424         return (PyObject *) result;
425     }
426 fail:
427     Py_XDECREF(start);
428     Py_XDECREF(stop);
429     Py_XDECREF(step);
430     Py_XDECREF(substart);
431     Py_XDECREF(substop);
432     Py_XDECREF(substep);
433     return NULL;
434 }
435 
436 /* Assumes (PyLong_CheckExact(ob) || PyBool_Check(ob)) */
437 static int
range_contains_long(rangeobject * r,PyObject * ob)438 range_contains_long(rangeobject *r, PyObject *ob)
439 {
440     PyObject *zero = _PyLong_GetZero();  // borrowed reference
441     int cmp1, cmp2, cmp3;
442     PyObject *tmp1 = NULL;
443     PyObject *tmp2 = NULL;
444     int result = -1;
445 
446     /* Check if the value can possibly be in the range. */
447 
448     cmp1 = PyObject_RichCompareBool(r->step, zero, Py_GT);
449     if (cmp1 == -1)
450         goto end;
451     if (cmp1 == 1) { /* positive steps: start <= ob < stop */
452         cmp2 = PyObject_RichCompareBool(r->start, ob, Py_LE);
453         cmp3 = PyObject_RichCompareBool(ob, r->stop, Py_LT);
454     }
455     else { /* negative steps: stop < ob <= start */
456         cmp2 = PyObject_RichCompareBool(ob, r->start, Py_LE);
457         cmp3 = PyObject_RichCompareBool(r->stop, ob, Py_LT);
458     }
459 
460     if (cmp2 == -1 || cmp3 == -1) /* TypeError */
461         goto end;
462     if (cmp2 == 0 || cmp3 == 0) { /* ob outside of range */
463         result = 0;
464         goto end;
465     }
466 
467     /* Check that the stride does not invalidate ob's membership. */
468     tmp1 = PyNumber_Subtract(ob, r->start);
469     if (tmp1 == NULL)
470         goto end;
471     tmp2 = PyNumber_Remainder(tmp1, r->step);
472     if (tmp2 == NULL)
473         goto end;
474     /* result = ((int(ob) - start) % step) == 0 */
475     result = PyObject_RichCompareBool(tmp2, zero, Py_EQ);
476   end:
477     Py_XDECREF(tmp1);
478     Py_XDECREF(tmp2);
479     return result;
480 }
481 
482 static int
range_contains(rangeobject * r,PyObject * ob)483 range_contains(rangeobject *r, PyObject *ob)
484 {
485     if (PyLong_CheckExact(ob) || PyBool_Check(ob))
486         return range_contains_long(r, ob);
487 
488     return (int)_PySequence_IterSearch((PyObject*)r, ob,
489                                        PY_ITERSEARCH_CONTAINS);
490 }
491 
492 /* Compare two range objects.  Return 1 for equal, 0 for not equal
493    and -1 on error.  The algorithm is roughly the C equivalent of
494 
495    if r0 is r1:
496        return True
497    if len(r0) != len(r1):
498        return False
499    if not len(r0):
500        return True
501    if r0.start != r1.start:
502        return False
503    if len(r0) == 1:
504        return True
505    return r0.step == r1.step
506 */
507 static int
range_equals(rangeobject * r0,rangeobject * r1)508 range_equals(rangeobject *r0, rangeobject *r1)
509 {
510     int cmp_result;
511 
512     if (r0 == r1)
513         return 1;
514     cmp_result = PyObject_RichCompareBool(r0->length, r1->length, Py_EQ);
515     /* Return False or error to the caller. */
516     if (cmp_result != 1)
517         return cmp_result;
518     cmp_result = PyObject_Not(r0->length);
519     /* Return True or error to the caller. */
520     if (cmp_result != 0)
521         return cmp_result;
522     cmp_result = PyObject_RichCompareBool(r0->start, r1->start, Py_EQ);
523     /* Return False or error to the caller. */
524     if (cmp_result != 1)
525         return cmp_result;
526     cmp_result = PyObject_RichCompareBool(r0->length, _PyLong_GetOne(), Py_EQ);
527     /* Return True or error to the caller. */
528     if (cmp_result != 0)
529         return cmp_result;
530     return PyObject_RichCompareBool(r0->step, r1->step, Py_EQ);
531 }
532 
533 static PyObject *
range_richcompare(PyObject * self,PyObject * other,int op)534 range_richcompare(PyObject *self, PyObject *other, int op)
535 {
536     int result;
537 
538     if (!PyRange_Check(other))
539         Py_RETURN_NOTIMPLEMENTED;
540     switch (op) {
541     case Py_NE:
542     case Py_EQ:
543         result = range_equals((rangeobject*)self, (rangeobject*)other);
544         if (result == -1)
545             return NULL;
546         if (op == Py_NE)
547             result = !result;
548         if (result)
549             Py_RETURN_TRUE;
550         else
551             Py_RETURN_FALSE;
552     case Py_LE:
553     case Py_GE:
554     case Py_LT:
555     case Py_GT:
556         Py_RETURN_NOTIMPLEMENTED;
557     default:
558         PyErr_BadArgument();
559         return NULL;
560     }
561 }
562 
563 /* Hash function for range objects.  Rough C equivalent of
564 
565    if not len(r):
566        return hash((len(r), None, None))
567    if len(r) == 1:
568        return hash((len(r), r.start, None))
569    return hash((len(r), r.start, r.step))
570 */
571 static Py_hash_t
range_hash(rangeobject * r)572 range_hash(rangeobject *r)
573 {
574     PyObject *t;
575     Py_hash_t result = -1;
576     int cmp_result;
577 
578     t = PyTuple_New(3);
579     if (!t)
580         return -1;
581     PyTuple_SET_ITEM(t, 0, Py_NewRef(r->length));
582     cmp_result = PyObject_Not(r->length);
583     if (cmp_result == -1)
584         goto end;
585     if (cmp_result == 1) {
586         PyTuple_SET_ITEM(t, 1, Py_NewRef(Py_None));
587         PyTuple_SET_ITEM(t, 2, Py_NewRef(Py_None));
588     }
589     else {
590         PyTuple_SET_ITEM(t, 1, Py_NewRef(r->start));
591         cmp_result = PyObject_RichCompareBool(r->length, _PyLong_GetOne(), Py_EQ);
592         if (cmp_result == -1)
593             goto end;
594         if (cmp_result == 1) {
595             PyTuple_SET_ITEM(t, 2, Py_NewRef(Py_None));
596         }
597         else {
598             PyTuple_SET_ITEM(t, 2, Py_NewRef(r->step));
599         }
600     }
601     result = PyObject_Hash(t);
602   end:
603     Py_DECREF(t);
604     return result;
605 }
606 
607 static PyObject *
range_count(rangeobject * r,PyObject * ob)608 range_count(rangeobject *r, PyObject *ob)
609 {
610     if (PyLong_CheckExact(ob) || PyBool_Check(ob)) {
611         int result = range_contains_long(r, ob);
612         if (result == -1)
613             return NULL;
614         return PyLong_FromLong(result);
615     } else {
616         Py_ssize_t count;
617         count = _PySequence_IterSearch((PyObject*)r, ob, PY_ITERSEARCH_COUNT);
618         if (count == -1)
619             return NULL;
620         return PyLong_FromSsize_t(count);
621     }
622 }
623 
624 static PyObject *
range_index(rangeobject * r,PyObject * ob)625 range_index(rangeobject *r, PyObject *ob)
626 {
627     int contains;
628 
629     if (!PyLong_CheckExact(ob) && !PyBool_Check(ob)) {
630         Py_ssize_t index;
631         index = _PySequence_IterSearch((PyObject*)r, ob, PY_ITERSEARCH_INDEX);
632         if (index == -1)
633             return NULL;
634         return PyLong_FromSsize_t(index);
635     }
636 
637     contains = range_contains_long(r, ob);
638     if (contains == -1)
639         return NULL;
640 
641     if (contains) {
642         PyObject *idx = PyNumber_Subtract(ob, r->start);
643         if (idx == NULL) {
644             return NULL;
645         }
646 
647         if (r->step == _PyLong_GetOne()) {
648             return idx;
649         }
650 
651         /* idx = (ob - r.start) // r.step */
652         PyObject *sidx = PyNumber_FloorDivide(idx, r->step);
653         Py_DECREF(idx);
654         return sidx;
655     }
656 
657     /* object is not in the range */
658     PyErr_Format(PyExc_ValueError, "%R is not in range", ob);
659     return NULL;
660 }
661 
662 static PySequenceMethods range_as_sequence = {
663     (lenfunc)range_length,      /* sq_length */
664     0,                          /* sq_concat */
665     0,                          /* sq_repeat */
666     (ssizeargfunc)range_item,   /* sq_item */
667     0,                          /* sq_slice */
668     0,                          /* sq_ass_item */
669     0,                          /* sq_ass_slice */
670     (objobjproc)range_contains, /* sq_contains */
671 };
672 
673 static PyObject *
range_repr(rangeobject * r)674 range_repr(rangeobject *r)
675 {
676     Py_ssize_t istep;
677 
678     /* Check for special case values for printing.  We don't always
679        need the step value.  We don't care about overflow. */
680     istep = PyNumber_AsSsize_t(r->step, NULL);
681     if (istep == -1 && PyErr_Occurred()) {
682         assert(!PyErr_ExceptionMatches(PyExc_OverflowError));
683         return NULL;
684     }
685 
686     if (istep == 1)
687         return PyUnicode_FromFormat("range(%R, %R)", r->start, r->stop);
688     else
689         return PyUnicode_FromFormat("range(%R, %R, %R)",
690                                     r->start, r->stop, r->step);
691 }
692 
693 /* Pickling support */
694 static PyObject *
range_reduce(rangeobject * r,PyObject * args)695 range_reduce(rangeobject *r, PyObject *args)
696 {
697     return Py_BuildValue("(O(OOO))", Py_TYPE(r),
698                          r->start, r->stop, r->step);
699 }
700 
701 static PyObject *
range_subscript(rangeobject * self,PyObject * item)702 range_subscript(rangeobject* self, PyObject* item)
703 {
704     if (_PyIndex_Check(item)) {
705         PyObject *i, *result;
706         i = PyNumber_Index(item);
707         if (!i)
708             return NULL;
709         result = compute_range_item(self, i);
710         Py_DECREF(i);
711         return result;
712     }
713     if (PySlice_Check(item)) {
714         return compute_slice(self, item);
715     }
716     PyErr_Format(PyExc_TypeError,
717                  "range indices must be integers or slices, not %.200s",
718                  Py_TYPE(item)->tp_name);
719     return NULL;
720 }
721 
722 
723 static PyMappingMethods range_as_mapping = {
724         (lenfunc)range_length,       /* mp_length */
725         (binaryfunc)range_subscript, /* mp_subscript */
726         (objobjargproc)0,            /* mp_ass_subscript */
727 };
728 
729 static int
range_bool(rangeobject * self)730 range_bool(rangeobject* self)
731 {
732     return PyObject_IsTrue(self->length);
733 }
734 
735 static PyNumberMethods range_as_number = {
736     .nb_bool = (inquiry)range_bool,
737 };
738 
739 static PyObject * range_iter(PyObject *seq);
740 static PyObject * range_reverse(PyObject *seq, PyObject *Py_UNUSED(ignored));
741 
742 PyDoc_STRVAR(reverse_doc,
743 "Return a reverse iterator.");
744 
745 PyDoc_STRVAR(count_doc,
746 "rangeobject.count(value) -> integer -- return number of occurrences of value");
747 
748 PyDoc_STRVAR(index_doc,
749 "rangeobject.index(value) -> integer -- return index of value.\n"
750 "Raise ValueError if the value is not present.");
751 
752 static PyMethodDef range_methods[] = {
753     {"__reversed__",    range_reverse,              METH_NOARGS, reverse_doc},
754     {"__reduce__",      (PyCFunction)range_reduce,  METH_NOARGS},
755     {"count",           (PyCFunction)range_count,   METH_O,      count_doc},
756     {"index",           (PyCFunction)range_index,   METH_O,      index_doc},
757     {NULL,              NULL}           /* sentinel */
758 };
759 
760 static PyMemberDef range_members[] = {
761     {"start",   Py_T_OBJECT_EX,    offsetof(rangeobject, start),   Py_READONLY},
762     {"stop",    Py_T_OBJECT_EX,    offsetof(rangeobject, stop),    Py_READONLY},
763     {"step",    Py_T_OBJECT_EX,    offsetof(rangeobject, step),    Py_READONLY},
764     {0}
765 };
766 
767 PyTypeObject PyRange_Type = {
768         PyVarObject_HEAD_INIT(&PyType_Type, 0)
769         "range",                /* Name of this type */
770         sizeof(rangeobject),    /* Basic object size */
771         0,                      /* Item size for varobject */
772         (destructor)range_dealloc, /* tp_dealloc */
773         0,                      /* tp_vectorcall_offset */
774         0,                      /* tp_getattr */
775         0,                      /* tp_setattr */
776         0,                      /* tp_as_async */
777         (reprfunc)range_repr,   /* tp_repr */
778         &range_as_number,       /* tp_as_number */
779         &range_as_sequence,     /* tp_as_sequence */
780         &range_as_mapping,      /* tp_as_mapping */
781         (hashfunc)range_hash,   /* tp_hash */
782         0,                      /* tp_call */
783         0,                      /* tp_str */
784         PyObject_GenericGetAttr,  /* tp_getattro */
785         0,                      /* tp_setattro */
786         0,                      /* tp_as_buffer */
787         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_SEQUENCE,  /* tp_flags */
788         range_doc,              /* tp_doc */
789         0,                      /* tp_traverse */
790         0,                      /* tp_clear */
791         range_richcompare,      /* tp_richcompare */
792         0,                      /* tp_weaklistoffset */
793         range_iter,             /* tp_iter */
794         0,                      /* tp_iternext */
795         range_methods,          /* tp_methods */
796         range_members,          /* tp_members */
797         0,                      /* tp_getset */
798         0,                      /* tp_base */
799         0,                      /* tp_dict */
800         0,                      /* tp_descr_get */
801         0,                      /* tp_descr_set */
802         0,                      /* tp_dictoffset */
803         0,                      /* tp_init */
804         0,                      /* tp_alloc */
805         range_new,              /* tp_new */
806         .tp_vectorcall = (vectorcallfunc)range_vectorcall
807 };
808 
809 /*********************** range Iterator **************************/
810 
811 /* There are 2 types of iterators, one for C longs, the other for
812    Python ints (ie, PyObjects).  This should make iteration fast
813    in the normal case, but possible for any numeric value.
814 */
815 
816 static PyObject *
rangeiter_next(_PyRangeIterObject * r)817 rangeiter_next(_PyRangeIterObject *r)
818 {
819     if (r->len > 0) {
820         long result = r->start;
821         r->start = result + r->step;
822         r->len--;
823         return PyLong_FromLong(result);
824     }
825     return NULL;
826 }
827 
828 static PyObject *
rangeiter_len(_PyRangeIterObject * r,PyObject * Py_UNUSED (ignored))829 rangeiter_len(_PyRangeIterObject *r, PyObject *Py_UNUSED(ignored))
830 {
831     return PyLong_FromLong(r->len);
832 }
833 
834 PyDoc_STRVAR(length_hint_doc,
835              "Private method returning an estimate of len(list(it)).");
836 
837 static PyObject *
rangeiter_reduce(_PyRangeIterObject * r,PyObject * Py_UNUSED (ignored))838 rangeiter_reduce(_PyRangeIterObject *r, PyObject *Py_UNUSED(ignored))
839 {
840     PyObject *start=NULL, *stop=NULL, *step=NULL;
841     PyObject *range;
842 
843     /* create a range object for pickling */
844     start = PyLong_FromLong(r->start);
845     if (start == NULL)
846         goto err;
847     stop = PyLong_FromLong(r->start + r->len * r->step);
848     if (stop == NULL)
849         goto err;
850     step = PyLong_FromLong(r->step);
851     if (step == NULL)
852         goto err;
853     range = (PyObject*)make_range_object(&PyRange_Type,
854                                start, stop, step);
855     if (range == NULL)
856         goto err;
857     /* return the result */
858     return Py_BuildValue("N(N)O", _PyEval_GetBuiltin(&_Py_ID(iter)),
859                          range, Py_None);
860 err:
861     Py_XDECREF(start);
862     Py_XDECREF(stop);
863     Py_XDECREF(step);
864     return NULL;
865 }
866 
867 static PyObject *
rangeiter_setstate(_PyRangeIterObject * r,PyObject * state)868 rangeiter_setstate(_PyRangeIterObject *r, PyObject *state)
869 {
870     long index = PyLong_AsLong(state);
871     if (index == -1 && PyErr_Occurred())
872         return NULL;
873     /* silently clip the index value */
874     if (index < 0)
875         index = 0;
876     else if (index > r->len)
877         index = r->len; /* exhausted iterator */
878     r->start += index * r->step;
879     r->len -= index;
880     Py_RETURN_NONE;
881 }
882 
883 PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
884 PyDoc_STRVAR(setstate_doc, "Set state information for unpickling.");
885 
886 static PyMethodDef rangeiter_methods[] = {
887     {"__length_hint__", (PyCFunction)rangeiter_len, METH_NOARGS,
888         length_hint_doc},
889     {"__reduce__", (PyCFunction)rangeiter_reduce, METH_NOARGS,
890         reduce_doc},
891     {"__setstate__", (PyCFunction)rangeiter_setstate, METH_O,
892         setstate_doc},
893     {NULL,              NULL}           /* sentinel */
894 };
895 
896 PyTypeObject PyRangeIter_Type = {
897         PyVarObject_HEAD_INIT(&PyType_Type, 0)
898         "range_iterator",                       /* tp_name */
899         sizeof(_PyRangeIterObject),             /* tp_basicsize */
900         0,                                      /* tp_itemsize */
901         /* methods */
902         (destructor)PyObject_Del,               /* tp_dealloc */
903         0,                                      /* tp_vectorcall_offset */
904         0,                                      /* tp_getattr */
905         0,                                      /* tp_setattr */
906         0,                                      /* tp_as_async */
907         0,                                      /* tp_repr */
908         0,                                      /* tp_as_number */
909         0,                                      /* tp_as_sequence */
910         0,                                      /* tp_as_mapping */
911         0,                                      /* tp_hash */
912         0,                                      /* tp_call */
913         0,                                      /* tp_str */
914         PyObject_GenericGetAttr,                /* tp_getattro */
915         0,                                      /* tp_setattro */
916         0,                                      /* tp_as_buffer */
917         Py_TPFLAGS_DEFAULT,                     /* tp_flags */
918         0,                                      /* tp_doc */
919         0,                                      /* tp_traverse */
920         0,                                      /* tp_clear */
921         0,                                      /* tp_richcompare */
922         0,                                      /* tp_weaklistoffset */
923         PyObject_SelfIter,                      /* tp_iter */
924         (iternextfunc)rangeiter_next,           /* tp_iternext */
925         rangeiter_methods,                      /* tp_methods */
926         0,                                      /* tp_members */
927 };
928 
929 /* Return number of items in range (lo, hi, step).  step != 0
930  * required.  The result always fits in an unsigned long.
931  */
932 static unsigned long
get_len_of_range(long lo,long hi,long step)933 get_len_of_range(long lo, long hi, long step)
934 {
935     /* -------------------------------------------------------------
936     If step > 0 and lo >= hi, or step < 0 and lo <= hi, the range is empty.
937     Else for step > 0, if n values are in the range, the last one is
938     lo + (n-1)*step, which must be <= hi-1.  Rearranging,
939     n <= (hi - lo - 1)/step + 1, so taking the floor of the RHS gives
940     the proper value.  Since lo < hi in this case, hi-lo-1 >= 0, so
941     the RHS is non-negative and so truncation is the same as the
942     floor.  Letting M be the largest positive long, the worst case
943     for the RHS numerator is hi=M, lo=-M-1, and then
944     hi-lo-1 = M-(-M-1)-1 = 2*M.  Therefore unsigned long has enough
945     precision to compute the RHS exactly.  The analysis for step < 0
946     is similar.
947     ---------------------------------------------------------------*/
948     assert(step != 0);
949     if (step > 0 && lo < hi)
950         return 1UL + (hi - 1UL - lo) / step;
951     else if (step < 0 && lo > hi)
952         return 1UL + (lo - 1UL - hi) / (0UL - step);
953     else
954         return 0UL;
955 }
956 
957 /* Initialize a rangeiter object.  If the length of the rangeiter object
958    is not representable as a C long, OverflowError is raised. */
959 
960 static PyObject *
fast_range_iter(long start,long stop,long step,long len)961 fast_range_iter(long start, long stop, long step, long len)
962 {
963     _PyRangeIterObject *it = PyObject_New(_PyRangeIterObject, &PyRangeIter_Type);
964     if (it == NULL)
965         return NULL;
966     it->start = start;
967     it->step = step;
968     it->len = len;
969     return (PyObject *)it;
970 }
971 
972 typedef struct {
973     PyObject_HEAD
974     PyObject *start;
975     PyObject *step;
976     PyObject *len;
977 } longrangeiterobject;
978 
979 static PyObject *
longrangeiter_len(longrangeiterobject * r,PyObject * no_args)980 longrangeiter_len(longrangeiterobject *r, PyObject *no_args)
981 {
982     Py_INCREF(r->len);
983     return r->len;
984 }
985 
986 static PyObject *
longrangeiter_reduce(longrangeiterobject * r,PyObject * Py_UNUSED (ignored))987 longrangeiter_reduce(longrangeiterobject *r, PyObject *Py_UNUSED(ignored))
988 {
989     PyObject *product, *stop=NULL;
990     PyObject *range;
991 
992     /* create a range object for pickling.  Must calculate the "stop" value */
993     product = PyNumber_Multiply(r->len, r->step);
994     if (product == NULL)
995         return NULL;
996     stop = PyNumber_Add(r->start, product);
997     Py_DECREF(product);
998     if (stop ==  NULL)
999         return NULL;
1000     range =  (PyObject*)make_range_object(&PyRange_Type,
1001                                Py_NewRef(r->start), stop, Py_NewRef(r->step));
1002     if (range == NULL) {
1003         Py_DECREF(r->start);
1004         Py_DECREF(stop);
1005         Py_DECREF(r->step);
1006         return NULL;
1007     }
1008 
1009     /* return the result */
1010     return Py_BuildValue("N(N)O", _PyEval_GetBuiltin(&_Py_ID(iter)),
1011                          range, Py_None);
1012 }
1013 
1014 static PyObject *
longrangeiter_setstate(longrangeiterobject * r,PyObject * state)1015 longrangeiter_setstate(longrangeiterobject *r, PyObject *state)
1016 {
1017     PyObject *zero = _PyLong_GetZero();  // borrowed reference
1018     int cmp;
1019 
1020     /* clip the value */
1021     cmp = PyObject_RichCompareBool(state, zero, Py_LT);
1022     if (cmp < 0)
1023         return NULL;
1024     if (cmp > 0) {
1025         state = zero;
1026     }
1027     else {
1028         cmp = PyObject_RichCompareBool(r->len, state, Py_LT);
1029         if (cmp < 0)
1030             return NULL;
1031         if (cmp > 0)
1032             state = r->len;
1033     }
1034     PyObject *product = PyNumber_Multiply(state, r->step);
1035     if (product == NULL)
1036         return NULL;
1037     PyObject *new_start = PyNumber_Add(r->start, product);
1038     Py_DECREF(product);
1039     if (new_start == NULL)
1040         return NULL;
1041     PyObject *new_len = PyNumber_Subtract(r->len, state);
1042     if (new_len == NULL) {
1043         Py_DECREF(new_start);
1044         return NULL;
1045     }
1046     PyObject *tmp = r->start;
1047     r->start = new_start;
1048     Py_SETREF(r->len, new_len);
1049     Py_DECREF(tmp);
1050     Py_RETURN_NONE;
1051 }
1052 
1053 static PyMethodDef longrangeiter_methods[] = {
1054     {"__length_hint__", (PyCFunction)longrangeiter_len, METH_NOARGS,
1055         length_hint_doc},
1056     {"__reduce__", (PyCFunction)longrangeiter_reduce, METH_NOARGS,
1057         reduce_doc},
1058     {"__setstate__", (PyCFunction)longrangeiter_setstate, METH_O,
1059         setstate_doc},
1060     {NULL,              NULL}           /* sentinel */
1061 };
1062 
1063 static void
longrangeiter_dealloc(longrangeiterobject * r)1064 longrangeiter_dealloc(longrangeiterobject *r)
1065 {
1066     Py_XDECREF(r->start);
1067     Py_XDECREF(r->step);
1068     Py_XDECREF(r->len);
1069     PyObject_Free(r);
1070 }
1071 
1072 static PyObject *
longrangeiter_next(longrangeiterobject * r)1073 longrangeiter_next(longrangeiterobject *r)
1074 {
1075     if (PyObject_RichCompareBool(r->len, _PyLong_GetZero(), Py_GT) != 1)
1076         return NULL;
1077 
1078     PyObject *new_start = PyNumber_Add(r->start, r->step);
1079     if (new_start == NULL) {
1080         return NULL;
1081     }
1082     PyObject *new_len = PyNumber_Subtract(r->len, _PyLong_GetOne());
1083     if (new_len == NULL) {
1084         Py_DECREF(new_start);
1085         return NULL;
1086     }
1087     PyObject *result = r->start;
1088     r->start = new_start;
1089     Py_SETREF(r->len, new_len);
1090     return result;
1091 }
1092 
1093 PyTypeObject PyLongRangeIter_Type = {
1094         PyVarObject_HEAD_INIT(&PyType_Type, 0)
1095         "longrange_iterator",                   /* tp_name */
1096         sizeof(longrangeiterobject),            /* tp_basicsize */
1097         0,                                      /* tp_itemsize */
1098         /* methods */
1099         (destructor)longrangeiter_dealloc,      /* tp_dealloc */
1100         0,                                      /* tp_vectorcall_offset */
1101         0,                                      /* tp_getattr */
1102         0,                                      /* tp_setattr */
1103         0,                                      /* tp_as_async */
1104         0,                                      /* tp_repr */
1105         0,                                      /* tp_as_number */
1106         0,                                      /* tp_as_sequence */
1107         0,                                      /* tp_as_mapping */
1108         0,                                      /* tp_hash */
1109         0,                                      /* tp_call */
1110         0,                                      /* tp_str */
1111         PyObject_GenericGetAttr,                /* tp_getattro */
1112         0,                                      /* tp_setattro */
1113         0,                                      /* tp_as_buffer */
1114         Py_TPFLAGS_DEFAULT,                     /* tp_flags */
1115         0,                                      /* tp_doc */
1116         0,                                      /* tp_traverse */
1117         0,                                      /* tp_clear */
1118         0,                                      /* tp_richcompare */
1119         0,                                      /* tp_weaklistoffset */
1120         PyObject_SelfIter,                      /* tp_iter */
1121         (iternextfunc)longrangeiter_next,       /* tp_iternext */
1122         longrangeiter_methods,                  /* tp_methods */
1123         0,
1124 };
1125 
1126 static PyObject *
range_iter(PyObject * seq)1127 range_iter(PyObject *seq)
1128 {
1129     rangeobject *r = (rangeobject *)seq;
1130     longrangeiterobject *it;
1131     long lstart, lstop, lstep;
1132     unsigned long ulen;
1133 
1134     assert(PyRange_Check(seq));
1135 
1136     /* If all three fields and the length convert to long, use the int
1137      * version */
1138     lstart = PyLong_AsLong(r->start);
1139     if (lstart == -1 && PyErr_Occurred()) {
1140         PyErr_Clear();
1141         goto long_range;
1142     }
1143     lstop = PyLong_AsLong(r->stop);
1144     if (lstop == -1 && PyErr_Occurred()) {
1145         PyErr_Clear();
1146         goto long_range;
1147     }
1148     lstep = PyLong_AsLong(r->step);
1149     if (lstep == -1 && PyErr_Occurred()) {
1150         PyErr_Clear();
1151         goto long_range;
1152     }
1153     ulen = get_len_of_range(lstart, lstop, lstep);
1154     if (ulen > (unsigned long)LONG_MAX) {
1155         goto long_range;
1156     }
1157     /* check for potential overflow of lstart + ulen * lstep */
1158     if (ulen) {
1159         if (lstep > 0) {
1160             if (lstop > LONG_MAX - (lstep - 1))
1161                 goto long_range;
1162         }
1163         else {
1164             if (lstop < LONG_MIN + (-1 - lstep))
1165                 goto long_range;
1166         }
1167     }
1168     return fast_range_iter(lstart, lstop, lstep, (long)ulen);
1169 
1170   long_range:
1171     it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type);
1172     if (it == NULL)
1173         return NULL;
1174 
1175     it->start = Py_NewRef(r->start);
1176     it->step = Py_NewRef(r->step);
1177     it->len = Py_NewRef(r->length);
1178     return (PyObject *)it;
1179 }
1180 
1181 static PyObject *
range_reverse(PyObject * seq,PyObject * Py_UNUSED (ignored))1182 range_reverse(PyObject *seq, PyObject *Py_UNUSED(ignored))
1183 {
1184     rangeobject *range = (rangeobject*) seq;
1185     longrangeiterobject *it;
1186     PyObject *sum, *diff, *product;
1187     long lstart, lstop, lstep, new_start, new_stop;
1188     unsigned long ulen;
1189 
1190     assert(PyRange_Check(seq));
1191 
1192     /* reversed(range(start, stop, step)) can be expressed as
1193        range(start+(n-1)*step, start-step, -step), where n is the number of
1194        integers in the range.
1195 
1196        If each of start, stop, step, -step, start-step, and the length
1197        of the iterator is representable as a C long, use the int
1198        version.  This excludes some cases where the reversed range is
1199        representable as a range_iterator, but it's good enough for
1200        common cases and it makes the checks simple. */
1201 
1202     lstart = PyLong_AsLong(range->start);
1203     if (lstart == -1 && PyErr_Occurred()) {
1204         PyErr_Clear();
1205         goto long_range;
1206     }
1207     lstop = PyLong_AsLong(range->stop);
1208     if (lstop == -1 && PyErr_Occurred()) {
1209         PyErr_Clear();
1210         goto long_range;
1211     }
1212     lstep = PyLong_AsLong(range->step);
1213     if (lstep == -1 && PyErr_Occurred()) {
1214         PyErr_Clear();
1215         goto long_range;
1216     }
1217     /* check for possible overflow of -lstep */
1218     if (lstep == LONG_MIN)
1219         goto long_range;
1220 
1221     /* check for overflow of lstart - lstep:
1222 
1223        for lstep > 0, need only check whether lstart - lstep < LONG_MIN.
1224        for lstep < 0, need only check whether lstart - lstep > LONG_MAX
1225 
1226        Rearrange these inequalities as:
1227 
1228            lstart - LONG_MIN < lstep  (lstep > 0)
1229            LONG_MAX - lstart < -lstep  (lstep < 0)
1230 
1231        and compute both sides as unsigned longs, to avoid the
1232        possibility of undefined behaviour due to signed overflow. */
1233 
1234     if (lstep > 0) {
1235          if ((unsigned long)lstart - LONG_MIN < (unsigned long)lstep)
1236             goto long_range;
1237     }
1238     else {
1239         if (LONG_MAX - (unsigned long)lstart < 0UL - lstep)
1240             goto long_range;
1241     }
1242 
1243     ulen = get_len_of_range(lstart, lstop, lstep);
1244     if (ulen > (unsigned long)LONG_MAX)
1245         goto long_range;
1246 
1247     new_stop = lstart - lstep;
1248     new_start = (long)(new_stop + ulen * lstep);
1249     return fast_range_iter(new_start, new_stop, -lstep, (long)ulen);
1250 
1251 long_range:
1252     it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type);
1253     if (it == NULL)
1254         return NULL;
1255     it->start = it->step = NULL;
1256 
1257     /* start + (len - 1) * step */
1258     it->len = Py_NewRef(range->length);
1259 
1260     diff = PyNumber_Subtract(it->len, _PyLong_GetOne());
1261     if (!diff)
1262         goto create_failure;
1263 
1264     product = PyNumber_Multiply(diff, range->step);
1265     Py_DECREF(diff);
1266     if (!product)
1267         goto create_failure;
1268 
1269     sum = PyNumber_Add(range->start, product);
1270     Py_DECREF(product);
1271     it->start = sum;
1272     if (!it->start)
1273         goto create_failure;
1274 
1275     it->step = PyNumber_Negative(range->step);
1276     if (!it->step)
1277         goto create_failure;
1278 
1279     return (PyObject *)it;
1280 
1281 create_failure:
1282     Py_DECREF(it);
1283     return NULL;
1284 }
1285