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