Coverage Report

Created: 2025-07-04 06:49

/src/cpython/Objects/sliceobject.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
Written by Jim Hugunin and Chris Chase.
3
4
This includes both the singular ellipsis object and slice objects.
5
6
Guido, feel free to do whatever you want in the way of copyrights
7
for this file.
8
*/
9
10
/*
11
Py_Ellipsis encodes the '...' rubber index token. It is similar to
12
the Py_NoneStruct in that there is no way to create other objects of
13
this type and there is exactly one in existence.
14
*/
15
16
#include "Python.h"
17
#include "pycore_abstract.h"      // _PyIndex_Check()
18
#include "pycore_freelist.h"      // _Py_FREELIST_FREE(), _Py_FREELIST_POP()
19
#include "pycore_long.h"          // _PyLong_GetZero()
20
#include "pycore_modsupport.h"    // _PyArg_NoKeywords()
21
#include "pycore_object.h"        // _PyObject_GC_TRACK()
22
23
24
42.5M
#define _PySlice_CAST(op) _Py_CAST(PySliceObject*, (op))
25
26
27
static PyObject *
28
ellipsis_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
29
0
{
30
0
    if (PyTuple_GET_SIZE(args) || (kwargs && PyDict_GET_SIZE(kwargs))) {
31
0
        PyErr_SetString(PyExc_TypeError, "EllipsisType takes no arguments");
32
0
        return NULL;
33
0
    }
34
0
    return Py_Ellipsis;
35
0
}
36
37
static void
38
ellipsis_dealloc(PyObject *ellipsis)
39
0
{
40
    /* This should never get called, but we also don't want to SEGV if
41
     * we accidentally decref Ellipsis out of existence. Instead,
42
     * since Ellipsis is an immortal object, re-set the reference count.
43
     */
44
0
    _Py_SetImmortal(ellipsis);
45
0
}
46
47
static PyObject *
48
ellipsis_repr(PyObject *op)
49
0
{
50
0
    return PyUnicode_FromString("Ellipsis");
51
0
}
52
53
static PyObject *
54
ellipsis_reduce(PyObject *op, PyObject *Py_UNUSED(ignored))
55
0
{
56
0
    return PyUnicode_FromString("Ellipsis");
57
0
}
58
59
static PyMethodDef ellipsis_methods[] = {
60
    {"__reduce__", ellipsis_reduce, METH_NOARGS, NULL},
61
    {NULL, NULL}
62
};
63
64
PyDoc_STRVAR(ellipsis_doc,
65
"ellipsis()\n"
66
"--\n\n"
67
"The type of the Ellipsis singleton.");
68
69
PyTypeObject PyEllipsis_Type = {
70
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
71
    "ellipsis",                         /* tp_name */
72
    0,                                  /* tp_basicsize */
73
    0,                                  /* tp_itemsize */
74
    ellipsis_dealloc,                   /* tp_dealloc */
75
    0,                                  /* tp_vectorcall_offset */
76
    0,                                  /* tp_getattr */
77
    0,                                  /* tp_setattr */
78
    0,                                  /* tp_as_async */
79
    ellipsis_repr,                      /* tp_repr */
80
    0,                                  /* tp_as_number */
81
    0,                                  /* tp_as_sequence */
82
    0,                                  /* tp_as_mapping */
83
    0,                                  /* tp_hash */
84
    0,                                  /* tp_call */
85
    0,                                  /* tp_str */
86
    PyObject_GenericGetAttr,            /* tp_getattro */
87
    0,                                  /* tp_setattro */
88
    0,                                  /* tp_as_buffer */
89
    Py_TPFLAGS_DEFAULT,                 /* tp_flags */
90
    ellipsis_doc,                       /* tp_doc */
91
    0,                                  /* tp_traverse */
92
    0,                                  /* tp_clear */
93
    0,                                  /* tp_richcompare */
94
    0,                                  /* tp_weaklistoffset */
95
    0,                                  /* tp_iter */
96
    0,                                  /* tp_iternext */
97
    ellipsis_methods,                   /* tp_methods */
98
    0,                                  /* tp_members */
99
    0,                                  /* tp_getset */
100
    0,                                  /* tp_base */
101
    0,                                  /* tp_dict */
102
    0,                                  /* tp_descr_get */
103
    0,                                  /* tp_descr_set */
104
    0,                                  /* tp_dictoffset */
105
    0,                                  /* tp_init */
106
    0,                                  /* tp_alloc */
107
    ellipsis_new,                       /* tp_new */
108
};
109
110
PyObject _Py_EllipsisObject = _PyObject_HEAD_INIT(&PyEllipsis_Type);
111
112
113
/* Slice object implementation */
114
115
/* start, stop, and step are python objects with None indicating no
116
   index is present.
117
*/
118
119
static PySliceObject *
120
_PyBuildSlice_Consume2(PyObject *start, PyObject *stop, PyObject *step)
121
40.9M
{
122
40.9M
    assert(start != NULL && stop != NULL && step != NULL);
123
40.9M
    PySliceObject *obj = _Py_FREELIST_POP(PySliceObject, slices);
124
40.9M
    if (obj == NULL) {
125
1.67k
        obj = PyObject_GC_New(PySliceObject, &PySlice_Type);
126
1.67k
        if (obj == NULL) {
127
0
            goto error;
128
0
        }
129
1.67k
    }
130
131
40.9M
    obj->start = start;
132
40.9M
    obj->stop = stop;
133
40.9M
    obj->step = Py_NewRef(step);
134
135
40.9M
    _PyObject_GC_TRACK(obj);
136
40.9M
    return obj;
137
0
error:
138
0
    Py_DECREF(start);
139
0
    Py_DECREF(stop);
140
0
    return NULL;
141
40.9M
}
142
143
PyObject *
144
PySlice_New(PyObject *start, PyObject *stop, PyObject *step)
145
2.53k
{
146
2.53k
    if (step == NULL) {
147
309
        step = Py_None;
148
309
    }
149
2.53k
    if (start == NULL) {
150
127
        start = Py_None;
151
127
    }
152
2.53k
    if (stop == NULL) {
153
208
        stop = Py_None;
154
208
    }
155
2.53k
    return (PyObject *)_PyBuildSlice_Consume2(Py_NewRef(start),
156
2.53k
                                              Py_NewRef(stop), step);
157
2.53k
}
158
159
PyObject *
160
_PyBuildSlice_ConsumeRefs(PyObject *start, PyObject *stop)
161
40.9M
{
162
40.9M
    assert(start != NULL && stop != NULL);
163
40.9M
    return (PyObject *)_PyBuildSlice_Consume2(start, stop, Py_None);
164
40.9M
}
165
166
PyObject *
167
_PySlice_FromIndices(Py_ssize_t istart, Py_ssize_t istop)
168
0
{
169
0
    PyObject *start, *end, *slice;
170
0
    start = PyLong_FromSsize_t(istart);
171
0
    if (!start)
172
0
        return NULL;
173
0
    end = PyLong_FromSsize_t(istop);
174
0
    if (!end) {
175
0
        Py_DECREF(start);
176
0
        return NULL;
177
0
    }
178
179
0
    slice = PySlice_New(start, end, NULL);
180
0
    Py_DECREF(start);
181
0
    Py_DECREF(end);
182
0
    return slice;
183
0
}
184
185
int
186
PySlice_GetIndices(PyObject *_r, Py_ssize_t length,
187
                   Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step)
188
0
{
189
0
    PySliceObject *r = (PySliceObject*)_r;
190
    /* XXX support long ints */
191
0
    if (r->step == Py_None) {
192
0
        *step = 1;
193
0
    } else {
194
0
        if (!PyLong_Check(r->step)) return -1;
195
0
        *step = PyLong_AsSsize_t(r->step);
196
0
    }
197
0
    if (r->start == Py_None) {
198
0
        *start = *step < 0 ? length-1 : 0;
199
0
    } else {
200
0
        if (!PyLong_Check(r->start)) return -1;
201
0
        *start = PyLong_AsSsize_t(r->start);
202
0
        if (*start < 0) *start += length;
203
0
    }
204
0
    if (r->stop == Py_None) {
205
0
        *stop = *step < 0 ? -1 : length;
206
0
    } else {
207
0
        if (!PyLong_Check(r->stop)) return -1;
208
0
        *stop = PyLong_AsSsize_t(r->stop);
209
0
        if (*stop < 0) *stop += length;
210
0
    }
211
0
    if (*stop > length) return -1;
212
0
    if (*start >= length) return -1;
213
0
    if (*step == 0) return -1;
214
0
    return 0;
215
0
}
216
217
int
218
PySlice_Unpack(PyObject *_r,
219
               Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step)
220
89.1M
{
221
89.1M
    PySliceObject *r = (PySliceObject*)_r;
222
    /* this is harder to get right than you might think */
223
224
89.1M
    static_assert(PY_SSIZE_T_MIN + 1 <= -PY_SSIZE_T_MAX,
225
89.1M
                  "-PY_SSIZE_T_MAX < PY_SSIZE_T_MIN + 1");
226
227
89.1M
    if (r->step == Py_None) {
228
89.1M
        *step = 1;
229
89.1M
    }
230
172
    else {
231
172
        if (!_PyEval_SliceIndex(r->step, step)) return -1;
232
172
        if (*step == 0) {
233
0
            PyErr_SetString(PyExc_ValueError,
234
0
                            "slice step cannot be zero");
235
0
            return -1;
236
0
        }
237
        /* Here *step might be -PY_SSIZE_T_MAX-1; in this case we replace it
238
         * with -PY_SSIZE_T_MAX.  This doesn't affect the semantics, and it
239
         * guards against later undefined behaviour resulting from code that
240
         * does "step = -step" as part of a slice reversal.
241
         */
242
172
        if (*step < -PY_SSIZE_T_MAX)
243
0
            *step = -PY_SSIZE_T_MAX;
244
172
    }
245
246
89.1M
    if (r->start == Py_None) {
247
34.8M
        *start = *step < 0 ? PY_SSIZE_T_MAX : 0;
248
34.8M
    }
249
54.3M
    else {
250
54.3M
        if (!_PyEval_SliceIndex(r->start, start)) return -1;
251
54.3M
    }
252
253
89.1M
    if (r->stop == Py_None) {
254
46.6M
        *stop = *step < 0 ? PY_SSIZE_T_MIN : PY_SSIZE_T_MAX;
255
46.6M
    }
256
42.5M
    else {
257
42.5M
        if (!_PyEval_SliceIndex(r->stop, stop)) return -1;
258
42.5M
    }
259
260
89.1M
    return 0;
261
89.1M
}
262
263
Py_ssize_t
264
PySlice_AdjustIndices(Py_ssize_t length,
265
                      Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t step)
266
89.1M
{
267
    /* this is harder to get right than you might think */
268
269
89.1M
    assert(step != 0);
270
89.1M
    assert(step >= -PY_SSIZE_T_MAX);
271
272
89.1M
    if (*start < 0) {
273
1.37M
        *start += length;
274
1.37M
        if (*start < 0) {
275
0
            *start = (step < 0) ? -1 : 0;
276
0
        }
277
1.37M
    }
278
87.7M
    else if (*start >= length) {
279
12.4M
        *start = (step < 0) ? length - 1 : length;
280
12.4M
    }
281
282
89.1M
    if (*stop < 0) {
283
1.59M
        *stop += length;
284
1.59M
        if (*stop < 0) {
285
128
            *stop = (step < 0) ? -1 : 0;
286
128
        }
287
1.59M
    }
288
87.5M
    else if (*stop >= length) {
289
51.4M
        *stop = (step < 0) ? length - 1 : length;
290
51.4M
    }
291
292
89.1M
    if (step < 0) {
293
128
        if (*stop < *start) {
294
128
            return (*start - *stop - 1) / (-step) + 1;
295
128
        }
296
128
    }
297
89.1M
    else {
298
89.1M
        if (*start < *stop) {
299
69.1M
            return (*stop - *start - 1) / step + 1;
300
69.1M
        }
301
89.1M
    }
302
20.0M
    return 0;
303
89.1M
}
304
305
#undef PySlice_GetIndicesEx
306
307
int
308
PySlice_GetIndicesEx(PyObject *_r, Py_ssize_t length,
309
                     Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step,
310
                     Py_ssize_t *slicelength)
311
0
{
312
0
    if (PySlice_Unpack(_r, start, stop, step) < 0)
313
0
        return -1;
314
0
    *slicelength = PySlice_AdjustIndices(length, start, stop, *step);
315
0
    return 0;
316
0
}
317
318
static PyObject *
319
slice_new(PyTypeObject *type, PyObject *args, PyObject *kw)
320
0
{
321
0
    PyObject *start, *stop, *step;
322
323
0
    start = stop = step = NULL;
324
325
0
    if (!_PyArg_NoKeywords("slice", kw))
326
0
        return NULL;
327
328
0
    if (!PyArg_UnpackTuple(args, "slice", 1, 3, &start, &stop, &step))
329
0
        return NULL;
330
331
    /* This swapping of stop and start is to maintain similarity with
332
       range(). */
333
0
    if (stop == NULL) {
334
0
        stop = start;
335
0
        start = NULL;
336
0
    }
337
0
    return PySlice_New(start, stop, step);
338
0
}
339
340
PyDoc_STRVAR(slice_doc,
341
"slice(stop)\n\
342
slice(start, stop[, step])\n\
343
\n\
344
Create a slice object.  This is used for extended slicing (e.g. a[0:10:2]).");
345
346
static void
347
slice_dealloc(PyObject *op)
348
40.9M
{
349
40.9M
    PySliceObject *r = _PySlice_CAST(op);
350
40.9M
    PyObject_GC_UnTrack(r);
351
40.9M
    Py_DECREF(r->step);
352
40.9M
    Py_DECREF(r->start);
353
40.9M
    Py_DECREF(r->stop);
354
40.9M
    _Py_FREELIST_FREE(slices, r, PyObject_GC_Del);
355
40.9M
}
356
357
static PyObject *
358
slice_repr(PyObject *op)
359
0
{
360
0
    PySliceObject *r = _PySlice_CAST(op);
361
0
    return PyUnicode_FromFormat("slice(%R, %R, %R)",
362
0
                                r->start, r->stop, r->step);
363
0
}
364
365
static PyMemberDef slice_members[] = {
366
    {"start", _Py_T_OBJECT, offsetof(PySliceObject, start), Py_READONLY},
367
    {"stop", _Py_T_OBJECT, offsetof(PySliceObject, stop), Py_READONLY},
368
    {"step", _Py_T_OBJECT, offsetof(PySliceObject, step), Py_READONLY},
369
    {0}
370
};
371
372
/* Helper function to convert a slice argument to a PyLong, and raise TypeError
373
   with a suitable message on failure. */
374
375
static PyObject*
376
evaluate_slice_index(PyObject *v)
377
491
{
378
491
    if (_PyIndex_Check(v)) {
379
491
        return PyNumber_Index(v);
380
491
    }
381
0
    else {
382
0
        PyErr_SetString(PyExc_TypeError,
383
0
                        "slice indices must be integers or "
384
0
                        "None or have an __index__ method");
385
0
        return NULL;
386
0
    }
387
491
}
388
389
/* Compute slice indices given a slice and length.  Return -1 on failure.  Used
390
   by slice.indices and rangeobject slicing.  Assumes that `len` is a
391
   nonnegative instance of PyLong. */
392
393
int
394
_PySlice_GetLongIndices(PySliceObject *self, PyObject *length,
395
                        PyObject **start_ptr, PyObject **stop_ptr,
396
                        PyObject **step_ptr)
397
491
{
398
491
    PyObject *start=NULL, *stop=NULL, *step=NULL;
399
491
    PyObject *upper=NULL, *lower=NULL;
400
491
    int step_is_negative, cmp_result;
401
402
    /* Convert step to an integer; raise for zero step. */
403
491
    if (self->step == Py_None) {
404
0
        step = _PyLong_GetOne();
405
0
        step_is_negative = 0;
406
0
    }
407
491
    else {
408
491
        step = evaluate_slice_index(self->step);
409
491
        if (step == NULL) {
410
0
            goto error;
411
0
        }
412
491
        assert(PyLong_Check(step));
413
414
491
        int step_sign;
415
491
        (void)PyLong_GetSign(step, &step_sign);
416
491
        if (step_sign == 0) {
417
0
            PyErr_SetString(PyExc_ValueError,
418
0
                            "slice step cannot be zero");
419
0
            goto error;
420
0
        }
421
491
        step_is_negative = step_sign < 0;
422
491
    }
423
424
    /* Find lower and upper bounds for start and stop. */
425
491
    if (step_is_negative) {
426
491
        lower = PyLong_FromLong(-1L);
427
491
        if (lower == NULL)
428
0
            goto error;
429
430
491
        upper = PyNumber_Add(length, lower);
431
491
        if (upper == NULL)
432
0
            goto error;
433
491
    }
434
0
    else {
435
0
        lower = _PyLong_GetZero();
436
0
        upper = Py_NewRef(length);
437
0
    }
438
439
    /* Compute start. */
440
491
    if (self->start == Py_None) {
441
491
        start = Py_NewRef(step_is_negative ? upper : lower);
442
491
    }
443
0
    else {
444
0
        start = evaluate_slice_index(self->start);
445
0
        if (start == NULL)
446
0
            goto error;
447
448
0
        if (_PyLong_IsNegative((PyLongObject *)start)) {
449
            /* start += length */
450
0
            PyObject *tmp = PyNumber_Add(start, length);
451
0
            Py_SETREF(start, tmp);
452
0
            if (start == NULL)
453
0
                goto error;
454
455
0
            cmp_result = PyObject_RichCompareBool(start, lower, Py_LT);
456
0
            if (cmp_result < 0)
457
0
                goto error;
458
0
            if (cmp_result) {
459
0
                Py_SETREF(start, Py_NewRef(lower));
460
0
            }
461
0
        }
462
0
        else {
463
0
            cmp_result = PyObject_RichCompareBool(start, upper, Py_GT);
464
0
            if (cmp_result < 0)
465
0
                goto error;
466
0
            if (cmp_result) {
467
0
                Py_SETREF(start, Py_NewRef(upper));
468
0
            }
469
0
        }
470
0
    }
471
472
    /* Compute stop. */
473
491
    if (self->stop == Py_None) {
474
491
        stop = Py_NewRef(step_is_negative ? lower : upper);
475
491
    }
476
0
    else {
477
0
        stop = evaluate_slice_index(self->stop);
478
0
        if (stop == NULL)
479
0
            goto error;
480
481
0
        if (_PyLong_IsNegative((PyLongObject *)stop)) {
482
            /* stop += length */
483
0
            PyObject *tmp = PyNumber_Add(stop, length);
484
0
            Py_SETREF(stop, tmp);
485
0
            if (stop == NULL)
486
0
                goto error;
487
488
0
            cmp_result = PyObject_RichCompareBool(stop, lower, Py_LT);
489
0
            if (cmp_result < 0)
490
0
                goto error;
491
0
            if (cmp_result) {
492
0
                Py_SETREF(stop, Py_NewRef(lower));
493
0
            }
494
0
        }
495
0
        else {
496
0
            cmp_result = PyObject_RichCompareBool(stop, upper, Py_GT);
497
0
            if (cmp_result < 0)
498
0
                goto error;
499
0
            if (cmp_result) {
500
0
                Py_SETREF(stop, Py_NewRef(upper));
501
0
            }
502
0
        }
503
0
    }
504
505
491
    *start_ptr = start;
506
491
    *stop_ptr = stop;
507
491
    *step_ptr = step;
508
491
    Py_DECREF(upper);
509
491
    Py_DECREF(lower);
510
491
    return 0;
511
512
0
  error:
513
0
    *start_ptr = *stop_ptr = *step_ptr = NULL;
514
0
    Py_XDECREF(start);
515
0
    Py_XDECREF(stop);
516
0
    Py_XDECREF(step);
517
0
    Py_XDECREF(upper);
518
0
    Py_XDECREF(lower);
519
0
    return -1;
520
491
}
521
522
/* Implementation of slice.indices. */
523
524
static PyObject*
525
slice_indices(PyObject *op, PyObject* len)
526
0
{
527
0
    PySliceObject *self = _PySlice_CAST(op);
528
0
    PyObject *start, *stop, *step;
529
0
    PyObject *length;
530
0
    int error;
531
532
    /* Convert length to an integer if necessary; raise for negative length. */
533
0
    length = PyNumber_Index(len);
534
0
    if (length == NULL)
535
0
        return NULL;
536
537
0
    if (_PyLong_IsNegative((PyLongObject *)length)) {
538
0
        PyErr_SetString(PyExc_ValueError,
539
0
                        "length should not be negative");
540
0
        Py_DECREF(length);
541
0
        return NULL;
542
0
    }
543
544
0
    error = _PySlice_GetLongIndices(self, length, &start, &stop, &step);
545
0
    Py_DECREF(length);
546
0
    if (error == -1)
547
0
        return NULL;
548
0
    else
549
0
        return Py_BuildValue("(NNN)", start, stop, step);
550
0
}
551
552
PyDoc_STRVAR(slice_indices_doc,
553
"S.indices(len) -> (start, stop, stride)\n\
554
\n\
555
Assuming a sequence of length len, calculate the start and stop\n\
556
indices, and the stride length of the extended slice described by\n\
557
S. Out of bounds indices are clipped in a manner consistent with the\n\
558
handling of normal slices.");
559
560
static PyObject *
561
slice_reduce(PyObject *op, PyObject *Py_UNUSED(ignored))
562
0
{
563
0
    PySliceObject *self = _PySlice_CAST(op);
564
0
    return Py_BuildValue("O(OOO)", Py_TYPE(self), self->start, self->stop, self->step);
565
0
}
566
567
PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
568
569
static PyMethodDef slice_methods[] = {
570
    {"indices", slice_indices, METH_O, slice_indices_doc},
571
    {"__reduce__", slice_reduce, METH_NOARGS, reduce_doc},
572
    {NULL, NULL}
573
};
574
575
static PyObject *
576
slice_richcompare(PyObject *v, PyObject *w, int op)
577
326
{
578
326
    if (!PySlice_Check(v) || !PySlice_Check(w))
579
0
        Py_RETURN_NOTIMPLEMENTED;
580
581
326
    if (v == w) {
582
0
        PyObject *res;
583
        /* XXX Do we really need this shortcut?
584
           There's a unit test for it, but is that fair? */
585
0
        switch (op) {
586
0
        case Py_EQ:
587
0
        case Py_LE:
588
0
        case Py_GE:
589
0
            res = Py_True;
590
0
            break;
591
0
        default:
592
0
            res = Py_False;
593
0
            break;
594
0
        }
595
0
        return Py_NewRef(res);
596
0
    }
597
598
599
326
    PyObject *t1 = PyTuple_Pack(3,
600
326
                                ((PySliceObject *)v)->start,
601
326
                                ((PySliceObject *)v)->stop,
602
326
                                ((PySliceObject *)v)->step);
603
326
    if (t1 == NULL) {
604
0
        return NULL;
605
0
    }
606
607
326
    PyObject *t2 = PyTuple_Pack(3,
608
326
                                ((PySliceObject *)w)->start,
609
326
                                ((PySliceObject *)w)->stop,
610
326
                                ((PySliceObject *)w)->step);
611
326
    if (t2 == NULL) {
612
0
        Py_DECREF(t1);
613
0
        return NULL;
614
0
    }
615
616
326
    PyObject *res = PyObject_RichCompare(t1, t2, op);
617
326
    Py_DECREF(t1);
618
326
    Py_DECREF(t2);
619
326
    return res;
620
326
}
621
622
static int
623
slice_traverse(PyObject *op, visitproc visit, void *arg)
624
1.59M
{
625
1.59M
    PySliceObject *v = _PySlice_CAST(op);
626
1.59M
    Py_VISIT(v->start);
627
1.59M
    Py_VISIT(v->stop);
628
1.59M
    Py_VISIT(v->step);
629
1.59M
    return 0;
630
1.59M
}
631
632
/* code based on tuplehash() of Objects/tupleobject.c */
633
#if SIZEOF_PY_UHASH_T > 4
634
3.88k
#define _PyHASH_XXPRIME_1 ((Py_uhash_t)11400714785074694791ULL)
635
3.88k
#define _PyHASH_XXPRIME_2 ((Py_uhash_t)14029467366897019727ULL)
636
1.29k
#define _PyHASH_XXPRIME_5 ((Py_uhash_t)2870177450012600261ULL)
637
3.88k
#define _PyHASH_XXROTATE(x) ((x << 31) | (x >> 33))  /* Rotate left 31 bits */
638
#else
639
#define _PyHASH_XXPRIME_1 ((Py_uhash_t)2654435761UL)
640
#define _PyHASH_XXPRIME_2 ((Py_uhash_t)2246822519UL)
641
#define _PyHASH_XXPRIME_5 ((Py_uhash_t)374761393UL)
642
#define _PyHASH_XXROTATE(x) ((x << 13) | (x >> 19))  /* Rotate left 13 bits */
643
#endif
644
645
static Py_hash_t
646
slice_hash(PyObject *op)
647
1.29k
{
648
1.29k
    PySliceObject *v = _PySlice_CAST(op);
649
1.29k
    Py_uhash_t acc = _PyHASH_XXPRIME_5;
650
3.88k
#define _PyHASH_SLICE_PART(com) { \
651
3.88k
    Py_uhash_t lane = PyObject_Hash(v->com); \
652
3.88k
    if(lane == (Py_uhash_t)-1) { \
653
0
        return -1; \
654
0
    } \
655
3.88k
    acc += lane * _PyHASH_XXPRIME_2; \
656
3.88k
    acc = _PyHASH_XXROTATE(acc); \
657
3.88k
    acc *= _PyHASH_XXPRIME_1; \
658
3.88k
}
659
1.29k
    _PyHASH_SLICE_PART(start);
660
1.29k
    _PyHASH_SLICE_PART(stop);
661
1.29k
    _PyHASH_SLICE_PART(step);
662
1.29k
#undef _PyHASH_SLICE_PART
663
1.29k
    if(acc == (Py_uhash_t)-1) {
664
0
        return 1546275796;
665
0
    }
666
1.29k
    return acc;
667
1.29k
}
668
669
PyTypeObject PySlice_Type = {
670
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
671
    "slice",                    /* Name of this type */
672
    sizeof(PySliceObject),      /* Basic object size */
673
    0,                          /* Item size for varobject */
674
    slice_dealloc,                              /* tp_dealloc */
675
    0,                                          /* tp_vectorcall_offset */
676
    0,                                          /* tp_getattr */
677
    0,                                          /* tp_setattr */
678
    0,                                          /* tp_as_async */
679
    slice_repr,                                 /* tp_repr */
680
    0,                                          /* tp_as_number */
681
    0,                                          /* tp_as_sequence */
682
    0,                                          /* tp_as_mapping */
683
    slice_hash,                                 /* tp_hash */
684
    0,                                          /* tp_call */
685
    0,                                          /* tp_str */
686
    PyObject_GenericGetAttr,                    /* tp_getattro */
687
    0,                                          /* tp_setattro */
688
    0,                                          /* tp_as_buffer */
689
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,    /* tp_flags */
690
    slice_doc,                                  /* tp_doc */
691
    slice_traverse,                             /* tp_traverse */
692
    0,                                          /* tp_clear */
693
    slice_richcompare,                          /* tp_richcompare */
694
    0,                                          /* tp_weaklistoffset */
695
    0,                                          /* tp_iter */
696
    0,                                          /* tp_iternext */
697
    slice_methods,                              /* tp_methods */
698
    slice_members,                              /* tp_members */
699
    0,                                          /* tp_getset */
700
    0,                                          /* tp_base */
701
    0,                                          /* tp_dict */
702
    0,                                          /* tp_descr_get */
703
    0,                                          /* tp_descr_set */
704
    0,                                          /* tp_dictoffset */
705
    0,                                          /* tp_init */
706
    0,                                          /* tp_alloc */
707
    slice_new,                                  /* tp_new */
708
};