LCOV - code coverage report
Current view: | top level - Objects - sliceobject.c (source / functions) |  |  | Hit | Total | Coverage
Test: | CPython 3.12 LCOV report [commit 5e6661bce9] |  | Lines: | 111 | 271 | 41.0 %
Date: | 2023-03-20 08:15:36 |  | Functions: | 12 | 22 | 54.5 %
|  |  | Branches: | 63 | 194 | 32.5 %

               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                 :            : };

Generated by: LCOV version 1.14