Coverage Report

Created: 2025-07-11 06:59

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