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