Coverage Report

Created: 2022-07-08 09:39

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