LCOV - code coverage report
Current view: top level - Objects - sliceobject.c (source / functions) Hit Total Coverage
Test: CPython 3.12 LCOV report [commit acb105a7c1f] Lines: 233 282 82.6 %
Date: 2022-07-20 13:12:14 Functions: 19 21 90.5 %
Branches: 132 186 71.0 %

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

Generated by: LCOV version 1.14