Branch data Line data Source code
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 : 3 : ellipsis_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
24 : : {
25 [ + + + + : 3 : if (PyTuple_GET_SIZE(args) || (kwargs && PyDict_GET_SIZE(kwargs))) {
+ - ]
26 : 2 : PyErr_SetString(PyExc_TypeError, "EllipsisType takes no arguments");
27 : 2 : return NULL;
28 : : }
29 : 1 : Py_INCREF(Py_Ellipsis);
30 : 1 : return Py_Ellipsis;
31 : : }
32 : :
33 : : static PyObject *
34 : 83 : ellipsis_repr(PyObject *op)
35 : : {
36 : 83 : return PyUnicode_FromString("Ellipsis");
37 : : }
38 : :
39 : : static PyObject *
40 : 213 : ellipsis_reduce(PyObject *op, PyObject *Py_UNUSED(ignored))
41 : : {
42 : 213 : 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 : 3125 : void _PySlice_Fini(PyInterpreterState *interp)
101 : : {
102 : 3125 : PySliceObject *obj = interp->slice_cache;
103 [ + - ]: 3125 : if (obj != NULL) {
104 : 3125 : interp->slice_cache = NULL;
105 : 3125 : PyObject_GC_Del(obj);
106 : : }
107 : 3125 : }
108 : :
109 : : /* start, stop, and step are python objects with None indicating no
110 : : index is present.
111 : : */
112 : :
113 : : static PySliceObject *
114 : 48841326 : _PyBuildSlice_Consume2(PyObject *start, PyObject *stop, PyObject *step)
115 : : {
116 : : assert(start != NULL && stop != NULL && step != NULL);
117 : :
118 : 48841326 : PyInterpreterState *interp = _PyInterpreterState_GET();
119 : : PySliceObject *obj;
120 [ + + ]: 48841326 : if (interp->slice_cache != NULL) {
121 : 48837013 : obj = interp->slice_cache;
122 : 48837013 : interp->slice_cache = NULL;
123 : 48837013 : _Py_NewReference((PyObject *)obj);
124 : : }
125 : : else {
126 : 4313 : obj = PyObject_GC_New(PySliceObject, &PySlice_Type);
127 [ - + ]: 4313 : if (obj == NULL) {
128 : 0 : goto error;
129 : : }
130 : : }
131 : :
132 : 48841326 : obj->start = start;
133 : 48841326 : obj->stop = stop;
134 : 48841326 : obj->step = Py_NewRef(step);
135 : :
136 : 48841326 : _PyObject_GC_TRACK(obj);
137 : 48841326 : return obj;
138 : 0 : error:
139 : 0 : Py_DECREF(start);
140 : 0 : Py_DECREF(stop);
141 : 0 : return NULL;
142 : : }
143 : :
144 : : PyObject *
145 : 644264 : PySlice_New(PyObject *start, PyObject *stop, PyObject *step)
146 : : {
147 [ + + ]: 644264 : if (step == NULL) {
148 : 92664 : step = Py_None;
149 : : }
150 [ + + ]: 644264 : if (start == NULL) {
151 : 34 : start = Py_None;
152 : : }
153 [ - + ]: 644264 : if (stop == NULL) {
154 : 0 : stop = Py_None;
155 : : }
156 : 644264 : Py_INCREF(start);
157 : 644264 : Py_INCREF(stop);
158 : 644264 : return (PyObject *) _PyBuildSlice_Consume2(start, stop, step);
159 : : }
160 : :
161 : : PyObject *
162 : 48197062 : _PyBuildSlice_ConsumeRefs(PyObject *start, PyObject *stop)
163 : : {
164 : : assert(start != NULL && stop != NULL);
165 : 48197062 : return (PyObject *)_PyBuildSlice_Consume2(start, stop, Py_None);
166 : : }
167 : :
168 : : PyObject *
169 : 17292 : _PySlice_FromIndices(Py_ssize_t istart, Py_ssize_t istop)
170 : : {
171 : : PyObject *start, *end, *slice;
172 : 17292 : start = PyLong_FromSsize_t(istart);
173 [ - + ]: 17292 : if (!start)
174 : 0 : return NULL;
175 : 17292 : end = PyLong_FromSsize_t(istop);
176 [ - + ]: 17292 : if (!end) {
177 : 0 : Py_DECREF(start);
178 : 0 : return NULL;
179 : : }
180 : :
181 : 17292 : slice = PySlice_New(start, end, NULL);
182 : 17292 : Py_DECREF(start);
183 : 17292 : Py_DECREF(end);
184 : 17292 : return slice;
185 : : }
186 : :
187 : : int
188 : 0 : PySlice_GetIndices(PyObject *_r, Py_ssize_t length,
189 : : Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step)
190 : : {
191 : 0 : PySliceObject *r = (PySliceObject*)_r;
192 : : /* XXX support long ints */
193 [ # # ]: 0 : if (r->step == Py_None) {
194 : 0 : *step = 1;
195 : : } else {
196 [ # # ]: 0 : if (!PyLong_Check(r->step)) return -1;
197 : 0 : *step = PyLong_AsSsize_t(r->step);
198 : : }
199 [ # # ]: 0 : if (r->start == Py_None) {
200 [ # # ]: 0 : *start = *step < 0 ? length-1 : 0;
201 : : } else {
202 [ # # ]: 0 : if (!PyLong_Check(r->start)) return -1;
203 : 0 : *start = PyLong_AsSsize_t(r->start);
204 [ # # ]: 0 : if (*start < 0) *start += length;
205 : : }
206 [ # # ]: 0 : if (r->stop == Py_None) {
207 [ # # ]: 0 : *stop = *step < 0 ? -1 : length;
208 : : } else {
209 [ # # ]: 0 : if (!PyLong_Check(r->stop)) return -1;
210 : 0 : *stop = PyLong_AsSsize_t(r->stop);
211 [ # # ]: 0 : if (*stop < 0) *stop += length;
212 : : }
213 [ # # ]: 0 : if (*stop > length) return -1;
214 [ # # ]: 0 : if (*start >= length) return -1;
215 [ # # ]: 0 : if (*step == 0) return -1;
216 : 0 : return 0;
217 : : }
218 : :
219 : : int
220 : 48629632 : PySlice_Unpack(PyObject *_r,
221 : : Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step)
222 : : {
223 : 48629632 : 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 [ + + ]: 48629632 : if (r->step == Py_None) {
230 : 48303885 : *step = 1;
231 : : }
232 : : else {
233 [ - + ]: 325747 : if (!_PyEval_SliceIndex(r->step, step)) return -1;
234 [ + + ]: 325747 : if (*step == 0) {
235 : 22 : PyErr_SetString(PyExc_ValueError,
236 : : "slice step cannot be zero");
237 : 22 : 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 [ + + ]: 325725 : if (*step < -PY_SSIZE_T_MAX)
245 : 8 : *step = -PY_SSIZE_T_MAX;
246 : : }
247 : :
248 [ + + ]: 48629610 : if (r->start == Py_None) {
249 [ + + ]: 25884238 : *start = *step < 0 ? PY_SSIZE_T_MAX : 0;
250 : : }
251 : : else {
252 [ + + ]: 22745372 : if (!_PyEval_SliceIndex(r->start, start)) return -1;
253 : : }
254 : :
255 [ + + ]: 48629598 : if (r->stop == Py_None) {
256 [ + + ]: 12359327 : *stop = *step < 0 ? PY_SSIZE_T_MIN : PY_SSIZE_T_MAX;
257 : : }
258 : : else {
259 [ + + ]: 36270271 : if (!_PyEval_SliceIndex(r->stop, stop)) return -1;
260 : : }
261 : :
262 : 48629597 : return 0;
263 : : }
264 : :
265 : : Py_ssize_t
266 : 48629597 : 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 [ + + ]: 48629597 : if (*start < 0) {
275 : 886741 : *start += length;
276 [ + + ]: 886741 : if (*start < 0) {
277 [ + + ]: 26199 : *start = (step < 0) ? -1 : 0;
278 : : }
279 : : }
280 [ + + ]: 47742856 : else if (*start >= length) {
281 [ + + ]: 5343997 : *start = (step < 0) ? length - 1 : length;
282 : : }
283 : :
284 [ + + ]: 48629597 : if (*stop < 0) {
285 : 746959 : *stop += length;
286 [ + + ]: 746959 : if (*stop < 0) {
287 [ + + ]: 168452 : *stop = (step < 0) ? -1 : 0;
288 : : }
289 : : }
290 [ + + ]: 47882638 : else if (*stop >= length) {
291 [ + + ]: 24013703 : *stop = (step < 0) ? length - 1 : length;
292 : : }
293 : :
294 [ + + ]: 48629597 : if (step < 0) {
295 [ + + ]: 196275 : if (*stop < *start) {
296 : 165974 : return (*start - *stop - 1) / (-step) + 1;
297 : : }
298 : : }
299 : : else {
300 [ + + ]: 48433322 : if (*start < *stop) {
301 : 43026336 : return (*stop - *start - 1) / step + 1;
302 : : }
303 : : }
304 : 5437287 : return 0;
305 : : }
306 : :
307 : : #undef PySlice_GetIndicesEx
308 : :
309 : : int
310 : 0 : 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 [ # # ]: 0 : if (PySlice_Unpack(_r, start, stop, step) < 0)
315 : 0 : return -1;
316 : 0 : *slicelength = PySlice_AdjustIndices(length, start, stop, *step);
317 : 0 : return 0;
318 : : }
319 : :
320 : : static PyObject *
321 : 8283 : slice_new(PyTypeObject *type, PyObject *args, PyObject *kw)
322 : : {
323 : : PyObject *start, *stop, *step;
324 : :
325 : 8283 : start = stop = step = NULL;
326 : :
327 [ + + - + ]: 8283 : if (!_PyArg_NoKeywords("slice", kw))
328 : 0 : return NULL;
329 : :
330 [ + + ]: 8283 : if (!PyArg_UnpackTuple(args, "slice", 1, 3, &start, &stop, &step))
331 : 2 : return NULL;
332 : :
333 : : /* This swapping of stop and start is to maintain similarity with
334 : : range(). */
335 [ + + ]: 8281 : if (stop == NULL) {
336 : 34 : stop = start;
337 : 34 : start = NULL;
338 : : }
339 : 8281 : 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 : 48841326 : slice_dealloc(PySliceObject *r)
350 : : {
351 : 48841326 : PyInterpreterState *interp = _PyInterpreterState_GET();
352 : 48841326 : _PyObject_GC_UNTRACK(r);
353 : 48841326 : Py_DECREF(r->step);
354 : 48841326 : Py_DECREF(r->start);
355 : 48841326 : Py_DECREF(r->stop);
356 [ + + ]: 48841326 : if (interp->slice_cache == NULL) {
357 : 48840147 : interp->slice_cache = r;
358 : : }
359 : : else {
360 : 1179 : PyObject_GC_Del(r);
361 : : }
362 : 48841326 : }
363 : :
364 : : static PyObject *
365 : 73 : slice_repr(PySliceObject *r)
366 : : {
367 : 73 : 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 : 338599 : evaluate_slice_index(PyObject *v)
382 : : {
383 [ + + ]: 338599 : if (_PyIndex_Check(v)) {
384 : 338596 : return PyNumber_Index(v);
385 : : }
386 : : else {
387 : 3 : PyErr_SetString(PyExc_TypeError,
388 : : "slice indices must be integers or "
389 : : "None or have an __index__ method");
390 : 3 : 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 : 279177 : _PySlice_GetLongIndices(PySliceObject *self, PyObject *length,
400 : : PyObject **start_ptr, PyObject **stop_ptr,
401 : : PyObject **step_ptr)
402 : : {
403 : 279177 : PyObject *start=NULL, *stop=NULL, *step=NULL;
404 : 279177 : PyObject *upper=NULL, *lower=NULL;
405 : : int step_is_negative, cmp_result;
406 : :
407 : : /* Convert step to an integer; raise for zero step. */
408 [ + + ]: 279177 : if (self->step == Py_None) {
409 : 3544 : step = _PyLong_GetOne();
410 : 3544 : Py_INCREF(step);
411 : 3544 : step_is_negative = 0;
412 : : }
413 : : else {
414 : : int step_sign;
415 : 275633 : step = evaluate_slice_index(self->step);
416 [ + + ]: 275633 : if (step == NULL)
417 : 1 : goto error;
418 : 275632 : step_sign = _PyLong_Sign(step);
419 [ + + ]: 275632 : if (step_sign == 0) {
420 : 865 : PyErr_SetString(PyExc_ValueError,
421 : : "slice step cannot be zero");
422 : 865 : goto error;
423 : : }
424 : 274767 : step_is_negative = step_sign < 0;
425 : : }
426 : :
427 : : /* Find lower and upper bounds for start and stop. */
428 [ + + ]: 278311 : if (step_is_negative) {
429 : 259172 : lower = PyLong_FromLong(-1L);
430 [ - + ]: 259172 : if (lower == NULL)
431 : 0 : goto error;
432 : :
433 : 259172 : upper = PyNumber_Add(length, lower);
434 [ - + ]: 259172 : if (upper == NULL)
435 : 0 : goto error;
436 : : }
437 : : else {
438 : 19139 : lower = _PyLong_GetZero();
439 : 19139 : Py_INCREF(lower);
440 : 19139 : upper = length;
441 : 19139 : Py_INCREF(upper);
442 : : }
443 : :
444 : : /* Compute start. */
445 [ + + ]: 278311 : if (self->start == Py_None) {
446 [ + + ]: 246840 : start = step_is_negative ? upper : lower;
447 : 246840 : Py_INCREF(start);
448 : : }
449 : : else {
450 : 31471 : start = evaluate_slice_index(self->start);
451 [ + + ]: 31471 : if (start == NULL)
452 : 1 : goto error;
453 : :
454 [ + + ]: 31470 : if (_PyLong_Sign(start) < 0) {
455 : : /* start += length */
456 : 14362 : PyObject *tmp = PyNumber_Add(start, length);
457 : 14362 : Py_DECREF(start);
458 : 14362 : start = tmp;
459 [ - + ]: 14362 : if (start == NULL)
460 : 0 : goto error;
461 : :
462 : 14362 : cmp_result = PyObject_RichCompareBool(start, lower, Py_LT);
463 [ - + ]: 14362 : if (cmp_result < 0)
464 : 0 : goto error;
465 [ + + ]: 14362 : if (cmp_result) {
466 : 7306 : Py_INCREF(lower);
467 : 7306 : Py_DECREF(start);
468 : 7306 : start = lower;
469 : : }
470 : : }
471 : : else {
472 : 17108 : cmp_result = PyObject_RichCompareBool(start, upper, Py_GT);
473 [ - + ]: 17108 : if (cmp_result < 0)
474 : 0 : goto error;
475 [ + + ]: 17108 : if (cmp_result) {
476 : 8563 : Py_INCREF(upper);
477 : 8563 : Py_DECREF(start);
478 : 8563 : start = upper;
479 : : }
480 : : }
481 : : }
482 : :
483 : : /* Compute stop. */
484 [ + + ]: 278310 : if (self->stop == Py_None) {
485 [ + + ]: 246815 : stop = step_is_negative ? lower : upper;
486 : 246815 : Py_INCREF(stop);
487 : : }
488 : : else {
489 : 31495 : stop = evaluate_slice_index(self->stop);
490 [ + + ]: 31495 : if (stop == NULL)
491 : 5 : goto error;
492 : :
493 [ + + ]: 31490 : if (_PyLong_Sign(stop) < 0) {
494 : : /* stop += length */
495 : 14376 : PyObject *tmp = PyNumber_Add(stop, length);
496 : 14376 : Py_DECREF(stop);
497 : 14376 : stop = tmp;
498 [ - + ]: 14376 : if (stop == NULL)
499 : 0 : goto error;
500 : :
501 : 14376 : cmp_result = PyObject_RichCompareBool(stop, lower, Py_LT);
502 [ - + ]: 14376 : if (cmp_result < 0)
503 : 0 : goto error;
504 [ + + ]: 14376 : if (cmp_result) {
505 : 7307 : Py_INCREF(lower);
506 : 7307 : Py_DECREF(stop);
507 : 7307 : stop = lower;
508 : : }
509 : : }
510 : : else {
511 : 17114 : cmp_result = PyObject_RichCompareBool(stop, upper, Py_GT);
512 [ - + ]: 17114 : if (cmp_result < 0)
513 : 0 : goto error;
514 [ + + ]: 17114 : if (cmp_result) {
515 : 8601 : Py_INCREF(upper);
516 : 8601 : Py_DECREF(stop);
517 : 8601 : stop = upper;
518 : : }
519 : : }
520 : : }
521 : :
522 : 278305 : *start_ptr = start;
523 : 278305 : *stop_ptr = stop;
524 : 278305 : *step_ptr = step;
525 : 278305 : Py_DECREF(upper);
526 : 278305 : Py_DECREF(lower);
527 : 278305 : return 0;
528 : :
529 : 872 : error:
530 : 872 : *start_ptr = *stop_ptr = *step_ptr = NULL;
531 : 872 : Py_XDECREF(start);
532 : 872 : Py_XDECREF(stop);
533 : 872 : Py_XDECREF(step);
534 : 872 : Py_XDECREF(upper);
535 : 872 : Py_XDECREF(lower);
536 : 872 : return -1;
537 : : }
538 : :
539 : : /* Implementation of slice.indices. */
540 : :
541 : : static PyObject*
542 : 20493 : 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 : 20493 : length = PyNumber_Index(len);
550 [ + + ]: 20493 : if (length == NULL)
551 : 1 : return NULL;
552 : :
553 [ + + ]: 20492 : if (_PyLong_Sign(length) < 0) {
554 : 2 : PyErr_SetString(PyExc_ValueError,
555 : : "length should not be negative");
556 : 2 : Py_DECREF(length);
557 : 2 : return NULL;
558 : : }
559 : :
560 : 20490 : error = _PySlice_GetLongIndices(self, length, &start, &stop, &step);
561 : 20490 : Py_DECREF(length);
562 [ + + ]: 20490 : if (error == -1)
563 : 870 : return NULL;
564 : : else
565 : 19620 : 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 : 48 : slice_reduce(PySliceObject* self, PyObject *Py_UNUSED(ignored))
578 : : {
579 : 48 : 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 : 30 : slice_richcompare(PyObject *v, PyObject *w, int op)
594 : : {
595 [ + - + + ]: 30 : if (!PySlice_Check(v) || !PySlice_Check(w))
596 : 3 : Py_RETURN_NOTIMPLEMENTED;
597 : :
598 [ + + ]: 27 : if (v == w) {
599 : : PyObject *res;
600 : : /* XXX Do we really need this shortcut?
601 : : There's a unit test for it, but is that fair? */
602 [ + - ]: 3 : switch (op) {
603 : 3 : case Py_EQ:
604 : : case Py_LE:
605 : : case Py_GE:
606 : 3 : res = Py_True;
607 : 3 : break;
608 : 0 : default:
609 : 0 : res = Py_False;
610 : 0 : break;
611 : : }
612 : 3 : Py_INCREF(res);
613 : 3 : return res;
614 : : }
615 : :
616 : :
617 : 24 : PyObject *t1 = PyTuple_Pack(3,
618 : : ((PySliceObject *)v)->start,
619 : : ((PySliceObject *)v)->stop,
620 : : ((PySliceObject *)v)->step);
621 [ - + ]: 24 : if (t1 == NULL) {
622 : 0 : return NULL;
623 : : }
624 : :
625 : 24 : PyObject *t2 = PyTuple_Pack(3,
626 : : ((PySliceObject *)w)->start,
627 : : ((PySliceObject *)w)->stop,
628 : : ((PySliceObject *)w)->step);
629 [ - + ]: 24 : if (t2 == NULL) {
630 : 0 : Py_DECREF(t1);
631 : 0 : return NULL;
632 : : }
633 : :
634 : 24 : PyObject *res = PyObject_RichCompare(t1, t2, op);
635 : 24 : Py_DECREF(t1);
636 : 24 : Py_DECREF(t2);
637 : 24 : return res;
638 : : }
639 : :
640 : : static int
641 : 8934 : slice_traverse(PySliceObject *v, visitproc visit, void *arg)
642 : : {
643 [ + - - + ]: 8934 : Py_VISIT(v->start);
644 [ + - - + ]: 8934 : Py_VISIT(v->stop);
645 [ + - - + ]: 8934 : Py_VISIT(v->step);
646 : 8934 : 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 : : };
|