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