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 : 0 : ellipsis_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
24 : : {
25 [ # # # # : 0 : if (PyTuple_GET_SIZE(args) || (kwargs && PyDict_GET_SIZE(kwargs))) {
# # ]
26 : 0 : PyErr_SetString(PyExc_TypeError, "EllipsisType takes no arguments");
27 : 0 : return NULL;
28 : : }
29 : 0 : return Py_NewRef(Py_Ellipsis);
30 : : }
31 : :
32 : : static PyObject *
33 : 3 : ellipsis_repr(PyObject *op)
34 : : {
35 : 3 : return PyUnicode_FromString("Ellipsis");
36 : : }
37 : :
38 : : static PyObject *
39 : 0 : ellipsis_reduce(PyObject *op, PyObject *Py_UNUSED(ignored))
40 : : {
41 : 0 : return PyUnicode_FromString("Ellipsis");
42 : : }
43 : :
44 : : static PyMethodDef ellipsis_methods[] = {
45 : : {"__reduce__", ellipsis_reduce, METH_NOARGS, NULL},
46 : : {NULL, NULL}
47 : : };
48 : :
49 : : PyTypeObject PyEllipsis_Type = {
50 : : PyVarObject_HEAD_INIT(&PyType_Type, 0)
51 : : "ellipsis", /* tp_name */
52 : : 0, /* tp_basicsize */
53 : : 0, /* tp_itemsize */
54 : : 0, /*never called*/ /* tp_dealloc */
55 : : 0, /* tp_vectorcall_offset */
56 : : 0, /* tp_getattr */
57 : : 0, /* tp_setattr */
58 : : 0, /* tp_as_async */
59 : : ellipsis_repr, /* tp_repr */
60 : : 0, /* tp_as_number */
61 : : 0, /* tp_as_sequence */
62 : : 0, /* tp_as_mapping */
63 : : 0, /* tp_hash */
64 : : 0, /* tp_call */
65 : : 0, /* tp_str */
66 : : PyObject_GenericGetAttr, /* tp_getattro */
67 : : 0, /* tp_setattro */
68 : : 0, /* tp_as_buffer */
69 : : Py_TPFLAGS_DEFAULT, /* tp_flags */
70 : : 0, /* tp_doc */
71 : : 0, /* tp_traverse */
72 : : 0, /* tp_clear */
73 : : 0, /* tp_richcompare */
74 : : 0, /* tp_weaklistoffset */
75 : : 0, /* tp_iter */
76 : : 0, /* tp_iternext */
77 : : ellipsis_methods, /* tp_methods */
78 : : 0, /* tp_members */
79 : : 0, /* tp_getset */
80 : : 0, /* tp_base */
81 : : 0, /* tp_dict */
82 : : 0, /* tp_descr_get */
83 : : 0, /* tp_descr_set */
84 : : 0, /* tp_dictoffset */
85 : : 0, /* tp_init */
86 : : 0, /* tp_alloc */
87 : : ellipsis_new, /* tp_new */
88 : : };
89 : :
90 : : PyObject _Py_EllipsisObject = {
91 : : _PyObject_EXTRA_INIT
92 : : 1, &PyEllipsis_Type
93 : : };
94 : :
95 : :
96 : : /* Slice object implementation */
97 : :
98 : :
99 : 25 : void _PySlice_Fini(PyInterpreterState *interp)
100 : : {
101 : 25 : PySliceObject *obj = interp->slice_cache;
102 [ + - ]: 25 : if (obj != NULL) {
103 : 25 : interp->slice_cache = NULL;
104 : 25 : PyObject_GC_Del(obj);
105 : : }
106 : 25 : }
107 : :
108 : : /* start, stop, and step are python objects with None indicating no
109 : : index is present.
110 : : */
111 : :
112 : : static PySliceObject *
113 : 83349 : _PyBuildSlice_Consume2(PyObject *start, PyObject *stop, PyObject *step)
114 : : {
115 : : assert(start != NULL && stop != NULL && step != NULL);
116 : :
117 : 83349 : PyInterpreterState *interp = _PyInterpreterState_GET();
118 : : PySliceObject *obj;
119 [ + + ]: 83349 : if (interp->slice_cache != NULL) {
120 : 83324 : obj = interp->slice_cache;
121 : 83324 : interp->slice_cache = NULL;
122 : 83324 : _Py_NewReference((PyObject *)obj);
123 : : }
124 : : else {
125 : 25 : obj = PyObject_GC_New(PySliceObject, &PySlice_Type);
126 [ - + ]: 25 : if (obj == NULL) {
127 : 0 : goto error;
128 : : }
129 : : }
130 : :
131 : 83349 : obj->start = start;
132 : 83349 : obj->stop = stop;
133 : 83349 : obj->step = Py_NewRef(step);
134 : :
135 : 83349 : _PyObject_GC_TRACK(obj);
136 : 83349 : return obj;
137 : 0 : error:
138 : 0 : Py_DECREF(start);
139 : 0 : Py_DECREF(stop);
140 : 0 : return NULL;
141 : : }
142 : :
143 : : PyObject *
144 : 1956 : PySlice_New(PyObject *start, PyObject *stop, PyObject *step)
145 : : {
146 [ + + ]: 1956 : if (step == NULL) {
147 : 779 : step = Py_None;
148 : : }
149 [ - + ]: 1956 : if (start == NULL) {
150 : 0 : start = Py_None;
151 : : }
152 [ - + ]: 1956 : if (stop == NULL) {
153 : 0 : stop = Py_None;
154 : : }
155 : 1956 : return (PyObject *)_PyBuildSlice_Consume2(Py_NewRef(start),
156 : : Py_NewRef(stop), step);
157 : : }
158 : :
159 : : PyObject *
160 : 81393 : _PyBuildSlice_ConsumeRefs(PyObject *start, PyObject *stop)
161 : : {
162 : : assert(start != NULL && stop != NULL);
163 : 81393 : return (PyObject *)_PyBuildSlice_Consume2(start, stop, Py_None);
164 : : }
165 : :
166 : : PyObject *
167 : 775 : _PySlice_FromIndices(Py_ssize_t istart, Py_ssize_t istop)
168 : : {
169 : : PyObject *start, *end, *slice;
170 : 775 : start = PyLong_FromSsize_t(istart);
171 [ - + ]: 775 : if (!start)
172 : 0 : return NULL;
173 : 775 : end = PyLong_FromSsize_t(istop);
174 [ - + ]: 775 : if (!end) {
175 : 0 : Py_DECREF(start);
176 : 0 : return NULL;
177 : : }
178 : :
179 : 775 : slice = PySlice_New(start, end, NULL);
180 : 775 : Py_DECREF(start);
181 : 775 : Py_DECREF(end);
182 : 775 : return slice;
183 : : }
184 : :
185 : : int
186 : 0 : PySlice_GetIndices(PyObject *_r, Py_ssize_t length,
187 : : Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step)
188 : : {
189 : 0 : PySliceObject *r = (PySliceObject*)_r;
190 : : /* XXX support long ints */
191 [ # # ]: 0 : if (r->step == Py_None) {
192 : 0 : *step = 1;
193 : : } else {
194 [ # # ]: 0 : if (!PyLong_Check(r->step)) return -1;
195 : 0 : *step = PyLong_AsSsize_t(r->step);
196 : : }
197 [ # # ]: 0 : if (r->start == Py_None) {
198 [ # # ]: 0 : *start = *step < 0 ? length-1 : 0;
199 : : } 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 : : }
204 [ # # ]: 0 : if (r->stop == Py_None) {
205 [ # # ]: 0 : *stop = *step < 0 ? -1 : length;
206 : : } 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 : : }
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 : : }
216 : :
217 : : int
218 : 83008 : PySlice_Unpack(PyObject *_r,
219 : : Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step)
220 : : {
221 : 83008 : PySliceObject *r = (PySliceObject*)_r;
222 : : /* this is harder to get right than you might think */
223 : :
224 : : static_assert(PY_SSIZE_T_MIN + 1 <= -PY_SSIZE_T_MAX,
225 : : "-PY_SSIZE_T_MAX < PY_SSIZE_T_MIN + 1");
226 : :
227 [ + + ]: 83008 : if (r->step == Py_None) {
228 : 82172 : *step = 1;
229 : : }
230 : : else {
231 [ - + ]: 836 : if (!_PyEval_SliceIndex(r->step, step)) return -1;
232 [ - + ]: 836 : if (*step == 0) {
233 : 0 : PyErr_SetString(PyExc_ValueError,
234 : : "slice step cannot be zero");
235 : 0 : return -1;
236 : : }
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 [ - + ]: 836 : if (*step < -PY_SSIZE_T_MAX)
243 : 0 : *step = -PY_SSIZE_T_MAX;
244 : : }
245 : :
246 [ + + ]: 83008 : if (r->start == Py_None) {
247 [ + + ]: 5995 : *start = *step < 0 ? PY_SSIZE_T_MAX : 0;
248 : : }
249 : : else {
250 [ - + ]: 77013 : if (!_PyEval_SliceIndex(r->start, start)) return -1;
251 : : }
252 : :
253 [ + + ]: 83008 : if (r->stop == Py_None) {
254 [ + + ]: 11757 : *stop = *step < 0 ? PY_SSIZE_T_MIN : PY_SSIZE_T_MAX;
255 : : }
256 : : else {
257 [ - + ]: 71251 : if (!_PyEval_SliceIndex(r->stop, stop)) return -1;
258 : : }
259 : :
260 : 83008 : return 0;
261 : : }
262 : :
263 : : Py_ssize_t
264 : 83008 : PySlice_AdjustIndices(Py_ssize_t length,
265 : : Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t step)
266 : : {
267 : : /* this is harder to get right than you might think */
268 : :
269 : : assert(step != 0);
270 : : assert(step >= -PY_SSIZE_T_MAX);
271 : :
272 [ + + ]: 83008 : if (*start < 0) {
273 : 1026 : *start += length;
274 [ - + ]: 1026 : if (*start < 0) {
275 [ # # ]: 0 : *start = (step < 0) ? -1 : 0;
276 : : }
277 : : }
278 [ + + ]: 81982 : else if (*start >= length) {
279 [ + + ]: 7408 : *start = (step < 0) ? length - 1 : length;
280 : : }
281 : :
282 [ + + ]: 83008 : if (*stop < 0) {
283 : 228 : *stop += length;
284 [ + + ]: 228 : if (*stop < 0) {
285 [ + - ]: 64 : *stop = (step < 0) ? -1 : 0;
286 : : }
287 : : }
288 [ + + ]: 82780 : else if (*stop >= length) {
289 [ - + ]: 12753 : *stop = (step < 0) ? length - 1 : length;
290 : : }
291 : :
292 [ + + ]: 83008 : if (step < 0) {
293 [ + - ]: 64 : if (*stop < *start) {
294 : 64 : return (*start - *stop - 1) / (-step) + 1;
295 : : }
296 : : }
297 : : else {
298 [ + + ]: 82944 : if (*start < *stop) {
299 : 75096 : return (*stop - *start - 1) / step + 1;
300 : : }
301 : : }
302 : 7848 : return 0;
303 : : }
304 : :
305 : : #undef PySlice_GetIndicesEx
306 : :
307 : : int
308 : 0 : 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 : : {
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 : : }
317 : :
318 : : static PyObject *
319 : 0 : slice_new(PyTypeObject *type, PyObject *args, PyObject *kw)
320 : : {
321 : : 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 : : }
337 : 0 : return PySlice_New(start, stop, step);
338 : : }
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 : 83349 : slice_dealloc(PySliceObject *r)
348 : : {
349 : 83349 : PyInterpreterState *interp = _PyInterpreterState_GET();
350 : 83349 : _PyObject_GC_UNTRACK(r);
351 : 83349 : Py_DECREF(r->step);
352 : 83349 : Py_DECREF(r->start);
353 : 83349 : Py_DECREF(r->stop);
354 [ + - ]: 83349 : if (interp->slice_cache == NULL) {
355 : 83349 : interp->slice_cache = r;
356 : : }
357 : : else {
358 : 0 : PyObject_GC_Del(r);
359 : : }
360 : 83349 : }
361 : :
362 : : static PyObject *
363 : 0 : slice_repr(PySliceObject *r)
364 : : {
365 : 0 : return PyUnicode_FromFormat("slice(%R, %R, %R)", r->start, r->stop, r->step);
366 : : }
367 : :
368 : : static PyMemberDef slice_members[] = {
369 : : {"start", T_OBJECT, offsetof(PySliceObject, start), READONLY},
370 : : {"stop", T_OBJECT, offsetof(PySliceObject, stop), READONLY},
371 : : {"step", T_OBJECT, offsetof(PySliceObject, step), READONLY},
372 : : {0}
373 : : };
374 : :
375 : : /* Helper function to convert a slice argument to a PyLong, and raise TypeError
376 : : with a suitable message on failure. */
377 : :
378 : : static PyObject*
379 : 341 : evaluate_slice_index(PyObject *v)
380 : : {
381 [ + - ]: 341 : if (_PyIndex_Check(v)) {
382 : 341 : return PyNumber_Index(v);
383 : : }
384 : : else {
385 : 0 : PyErr_SetString(PyExc_TypeError,
386 : : "slice indices must be integers or "
387 : : "None or have an __index__ method");
388 : 0 : return NULL;
389 : : }
390 : : }
391 : :
392 : : /* Compute slice indices given a slice and length. Return -1 on failure. Used
393 : : by slice.indices and rangeobject slicing. Assumes that `len` is a
394 : : nonnegative instance of PyLong. */
395 : :
396 : : int
397 : 341 : _PySlice_GetLongIndices(PySliceObject *self, PyObject *length,
398 : : PyObject **start_ptr, PyObject **stop_ptr,
399 : : PyObject **step_ptr)
400 : : {
401 : 341 : PyObject *start=NULL, *stop=NULL, *step=NULL;
402 : 341 : PyObject *upper=NULL, *lower=NULL;
403 : : int step_is_negative, cmp_result;
404 : :
405 : : /* Convert step to an integer; raise for zero step. */
406 [ - + ]: 341 : if (self->step == Py_None) {
407 : 0 : step = Py_NewRef(_PyLong_GetOne());
408 : 0 : step_is_negative = 0;
409 : : }
410 : : else {
411 : : int step_sign;
412 : 341 : step = evaluate_slice_index(self->step);
413 [ - + ]: 341 : if (step == NULL)
414 : 0 : goto error;
415 : 341 : step_sign = _PyLong_Sign(step);
416 [ - + ]: 341 : if (step_sign == 0) {
417 : 0 : PyErr_SetString(PyExc_ValueError,
418 : : "slice step cannot be zero");
419 : 0 : goto error;
420 : : }
421 : 341 : step_is_negative = step_sign < 0;
422 : : }
423 : :
424 : : /* Find lower and upper bounds for start and stop. */
425 [ + - ]: 341 : if (step_is_negative) {
426 : 341 : lower = PyLong_FromLong(-1L);
427 [ - + ]: 341 : if (lower == NULL)
428 : 0 : goto error;
429 : :
430 : 341 : upper = PyNumber_Add(length, lower);
431 [ - + ]: 341 : if (upper == NULL)
432 : 0 : goto error;
433 : : }
434 : : else {
435 : 0 : lower = Py_NewRef(_PyLong_GetZero());
436 : 0 : upper = Py_NewRef(length);
437 : : }
438 : :
439 : : /* Compute start. */
440 [ + - ]: 341 : if (self->start == Py_None) {
441 [ + - ]: 341 : start = Py_NewRef(step_is_negative ? upper : lower);
442 : : }
443 : : else {
444 : 0 : start = evaluate_slice_index(self->start);
445 [ # # ]: 0 : if (start == NULL)
446 : 0 : goto error;
447 : :
448 [ # # ]: 0 : if (_PyLong_Sign(start) < 0) {
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 : : }
461 : : }
462 : : 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 : : }
469 : : }
470 : : }
471 : :
472 : : /* Compute stop. */
473 [ + - ]: 341 : if (self->stop == Py_None) {
474 [ + - ]: 341 : stop = Py_NewRef(step_is_negative ? lower : upper);
475 : : }
476 : : else {
477 : 0 : stop = evaluate_slice_index(self->stop);
478 [ # # ]: 0 : if (stop == NULL)
479 : 0 : goto error;
480 : :
481 [ # # ]: 0 : if (_PyLong_Sign(stop) < 0) {
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 : : }
494 : : }
495 : : 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 : : }
502 : : }
503 : : }
504 : :
505 : 341 : *start_ptr = start;
506 : 341 : *stop_ptr = stop;
507 : 341 : *step_ptr = step;
508 : 341 : Py_DECREF(upper);
509 : 341 : Py_DECREF(lower);
510 : 341 : 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 : : }
521 : :
522 : : /* Implementation of slice.indices. */
523 : :
524 : : static PyObject*
525 : 0 : slice_indices(PySliceObject* self, PyObject* len)
526 : : {
527 : : PyObject *start, *stop, *step;
528 : : PyObject *length;
529 : : int error;
530 : :
531 : : /* Convert length to an integer if necessary; raise for negative length. */
532 : 0 : length = PyNumber_Index(len);
533 [ # # ]: 0 : if (length == NULL)
534 : 0 : return NULL;
535 : :
536 [ # # ]: 0 : if (_PyLong_Sign(length) < 0) {
537 : 0 : PyErr_SetString(PyExc_ValueError,
538 : : "length should not be negative");
539 : 0 : Py_DECREF(length);
540 : 0 : return NULL;
541 : : }
542 : :
543 : 0 : error = _PySlice_GetLongIndices(self, length, &start, &stop, &step);
544 : 0 : Py_DECREF(length);
545 [ # # ]: 0 : if (error == -1)
546 : 0 : return NULL;
547 : : else
548 : 0 : return Py_BuildValue("(NNN)", start, stop, step);
549 : : }
550 : :
551 : : PyDoc_STRVAR(slice_indices_doc,
552 : : "S.indices(len) -> (start, stop, stride)\n\
553 : : \n\
554 : : Assuming a sequence of length len, calculate the start and stop\n\
555 : : indices, and the stride length of the extended slice described by\n\
556 : : S. Out of bounds indices are clipped in a manner consistent with the\n\
557 : : handling of normal slices.");
558 : :
559 : : static PyObject *
560 : 0 : slice_reduce(PySliceObject* self, PyObject *Py_UNUSED(ignored))
561 : : {
562 : 0 : return Py_BuildValue("O(OOO)", Py_TYPE(self), self->start, self->stop, self->step);
563 : : }
564 : :
565 : : PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
566 : :
567 : : static PyMethodDef slice_methods[] = {
568 : : {"indices", (PyCFunction)slice_indices,
569 : : METH_O, slice_indices_doc},
570 : : {"__reduce__", (PyCFunction)slice_reduce,
571 : : METH_NOARGS, reduce_doc},
572 : : {NULL, NULL}
573 : : };
574 : :
575 : : static PyObject *
576 : 0 : slice_richcompare(PyObject *v, PyObject *w, int op)
577 : : {
578 [ # # # # ]: 0 : if (!PySlice_Check(v) || !PySlice_Check(w))
579 : 0 : Py_RETURN_NOTIMPLEMENTED;
580 : :
581 [ # # ]: 0 : if (v == w) {
582 : : 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 : : case Py_LE:
588 : : case Py_GE:
589 : 0 : res = Py_True;
590 : 0 : break;
591 : 0 : default:
592 : 0 : res = Py_False;
593 : 0 : break;
594 : : }
595 : 0 : return Py_NewRef(res);
596 : : }
597 : :
598 : :
599 : 0 : PyObject *t1 = PyTuple_Pack(3,
600 : : ((PySliceObject *)v)->start,
601 : : ((PySliceObject *)v)->stop,
602 : : ((PySliceObject *)v)->step);
603 [ # # ]: 0 : if (t1 == NULL) {
604 : 0 : return NULL;
605 : : }
606 : :
607 : 0 : PyObject *t2 = PyTuple_Pack(3,
608 : : ((PySliceObject *)w)->start,
609 : : ((PySliceObject *)w)->stop,
610 : : ((PySliceObject *)w)->step);
611 [ # # ]: 0 : if (t2 == NULL) {
612 : 0 : Py_DECREF(t1);
613 : 0 : return NULL;
614 : : }
615 : :
616 : 0 : PyObject *res = PyObject_RichCompare(t1, t2, op);
617 : 0 : Py_DECREF(t1);
618 : 0 : Py_DECREF(t2);
619 : 0 : return res;
620 : : }
621 : :
622 : : static int
623 : 2 : slice_traverse(PySliceObject *v, visitproc visit, void *arg)
624 : : {
625 [ + - - + ]: 2 : Py_VISIT(v->start);
626 [ + - - + ]: 2 : Py_VISIT(v->stop);
627 [ + - - + ]: 2 : Py_VISIT(v->step);
628 : 2 : return 0;
629 : : }
630 : :
631 : : /* code based on tuplehash() of Objects/tupleobject.c */
632 : : #if SIZEOF_PY_UHASH_T > 4
633 : : #define _PyHASH_XXPRIME_1 ((Py_uhash_t)11400714785074694791ULL)
634 : : #define _PyHASH_XXPRIME_2 ((Py_uhash_t)14029467366897019727ULL)
635 : : #define _PyHASH_XXPRIME_5 ((Py_uhash_t)2870177450012600261ULL)
636 : : #define _PyHASH_XXROTATE(x) ((x << 31) | (x >> 33)) /* Rotate left 31 bits */
637 : : #else
638 : : #define _PyHASH_XXPRIME_1 ((Py_uhash_t)2654435761UL)
639 : : #define _PyHASH_XXPRIME_2 ((Py_uhash_t)2246822519UL)
640 : : #define _PyHASH_XXPRIME_5 ((Py_uhash_t)374761393UL)
641 : : #define _PyHASH_XXROTATE(x) ((x << 13) | (x >> 19)) /* Rotate left 13 bits */
642 : : #endif
643 : :
644 : : static Py_hash_t
645 : 0 : slicehash(PySliceObject *v)
646 : : {
647 : 0 : Py_uhash_t acc = _PyHASH_XXPRIME_5;
648 : : #define _PyHASH_SLICE_PART(com) { \
649 : : Py_uhash_t lane = PyObject_Hash(v->com); \
650 : : if(lane == (Py_uhash_t)-1) { \
651 : : return -1; \
652 : : } \
653 : : acc += lane * _PyHASH_XXPRIME_2; \
654 : : acc = _PyHASH_XXROTATE(acc); \
655 : : acc *= _PyHASH_XXPRIME_1; \
656 : : }
657 [ # # ]: 0 : _PyHASH_SLICE_PART(start);
658 [ # # ]: 0 : _PyHASH_SLICE_PART(stop);
659 [ # # ]: 0 : _PyHASH_SLICE_PART(step);
660 : : #undef _PyHASH_SLICE_PART
661 [ # # ]: 0 : if(acc == (Py_uhash_t)-1) {
662 : 0 : return 1546275796;
663 : : }
664 : 0 : return acc;
665 : : }
666 : :
667 : : PyTypeObject PySlice_Type = {
668 : : PyVarObject_HEAD_INIT(&PyType_Type, 0)
669 : : "slice", /* Name of this type */
670 : : sizeof(PySliceObject), /* Basic object size */
671 : : 0, /* Item size for varobject */
672 : : (destructor)slice_dealloc, /* tp_dealloc */
673 : : 0, /* tp_vectorcall_offset */
674 : : 0, /* tp_getattr */
675 : : 0, /* tp_setattr */
676 : : 0, /* tp_as_async */
677 : : (reprfunc)slice_repr, /* tp_repr */
678 : : 0, /* tp_as_number */
679 : : 0, /* tp_as_sequence */
680 : : 0, /* tp_as_mapping */
681 : : (hashfunc)slicehash, /* tp_hash */
682 : : 0, /* tp_call */
683 : : 0, /* tp_str */
684 : : PyObject_GenericGetAttr, /* tp_getattro */
685 : : 0, /* tp_setattro */
686 : : 0, /* tp_as_buffer */
687 : : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
688 : : slice_doc, /* tp_doc */
689 : : (traverseproc)slice_traverse, /* tp_traverse */
690 : : 0, /* tp_clear */
691 : : slice_richcompare, /* tp_richcompare */
692 : : 0, /* tp_weaklistoffset */
693 : : 0, /* tp_iter */
694 : : 0, /* tp_iternext */
695 : : slice_methods, /* tp_methods */
696 : : slice_members, /* tp_members */
697 : : 0, /* tp_getset */
698 : : 0, /* tp_base */
699 : : 0, /* tp_dict */
700 : : 0, /* tp_descr_get */
701 : : 0, /* tp_descr_set */
702 : : 0, /* tp_dictoffset */
703 : : 0, /* tp_init */
704 : : 0, /* tp_alloc */
705 : : slice_new, /* tp_new */
706 : : };
|