LCOV - code coverage report
Current view: top level - Objects - sliceobject.c (source / functions) Hit Total Coverage
Test: CPython lcov report Lines: 237 286 82.9 %
Date: 2022-07-07 18:19:46 Functions: 19 21 90.5 %

          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        3120 : void _PySlice_Fini(PyInterpreterState *interp)
     101             : {
     102        3120 :     PySliceObject *obj = interp->slice_cache;
     103        3120 :     if (obj != NULL) {
     104        3120 :         interp->slice_cache = NULL;
     105        3120 :         PyObject_GC_Del(obj);
     106             :     }
     107        3120 : }
     108             : 
     109             : /* start, stop, and step are python objects with None indicating no
     110             :    index is present.
     111             : */
     112             : 
     113             : static PySliceObject *
     114    49051500 : _PyBuildSlice_Consume2(PyObject *start, PyObject *stop, PyObject *step)
     115             : {
     116    49051500 :     assert(start != NULL && stop != NULL && step != NULL);
     117             : 
     118    49051500 :     PyInterpreterState *interp = _PyInterpreterState_GET();
     119             :     PySliceObject *obj;
     120    49051500 :     if (interp->slice_cache != NULL) {
     121    49047200 :         obj = interp->slice_cache;
     122    49047200 :         interp->slice_cache = NULL;
     123    49047200 :         _Py_NewReference((PyObject *)obj);
     124             :     }
     125             :     else {
     126        4321 :         obj = PyObject_GC_New(PySliceObject, &PySlice_Type);
     127        4321 :         if (obj == NULL) {
     128           0 :             goto error;
     129             :         }
     130             :     }
     131             : 
     132    49051500 :     obj->start = start;
     133    49051500 :     obj->stop = stop;
     134    49051500 :     obj->step = Py_NewRef(step);
     135             : 
     136    49051500 :     _PyObject_GC_TRACK(obj);
     137    49051500 :     return obj;
     138           0 : error:
     139           0 :     Py_DECREF(start);
     140           0 :     Py_DECREF(stop);
     141           0 :     return NULL;
     142             : }
     143             : 
     144             : PyObject *
     145      612261 : PySlice_New(PyObject *start, PyObject *stop, PyObject *step)
     146             : {
     147      612261 :     if (step == NULL) {
     148       91991 :         step = Py_None;
     149             :     }
     150      612261 :     if (start == NULL) {
     151          32 :         start = Py_None;
     152             :     }
     153      612261 :     if (stop == NULL) {
     154           0 :         stop = Py_None;
     155             :     }
     156      612261 :     Py_INCREF(start);
     157      612261 :     Py_INCREF(stop);
     158      612261 :     return (PyObject *) _PyBuildSlice_Consume2(start, stop, step);
     159             : }
     160             : 
     161             : PyObject *
     162    48439300 : _PyBuildSlice_ConsumeRefs(PyObject *start, PyObject *stop)
     163             : {
     164    48439300 :     assert(start != NULL && stop != NULL);
     165    48439300 :     return (PyObject *)_PyBuildSlice_Consume2(start, stop, Py_None);
     166             : }
     167             : 
     168             : PyObject *
     169       17245 : _PySlice_FromIndices(Py_ssize_t istart, Py_ssize_t istop)
     170             : {
     171             :     PyObject *start, *end, *slice;
     172       17245 :     start = PyLong_FromSsize_t(istart);
     173       17245 :     if (!start)
     174           0 :         return NULL;
     175       17245 :     end = PyLong_FromSsize_t(istop);
     176       17245 :     if (!end) {
     177           0 :         Py_DECREF(start);
     178           0 :         return NULL;
     179             :     }
     180             : 
     181       17245 :     slice = PySlice_New(start, end, NULL);
     182       17245 :     Py_DECREF(start);
     183       17245 :     Py_DECREF(end);
     184       17245 :     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    48839400 : PySlice_Unpack(PyObject *_r,
     221             :                Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step)
     222             : {
     223    48839400 :     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    48839400 :     if (r->step == Py_None) {
     230    48545400 :         *step = 1;
     231             :     }
     232             :     else {
     233      293913 :         if (!_PyEval_SliceIndex(r->step, step)) return -1;
     234      293913 :         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      293891 :         if (*step < -PY_SSIZE_T_MAX)
     245           8 :             *step = -PY_SSIZE_T_MAX;
     246             :     }
     247             : 
     248    48839300 :     if (r->start == Py_None) {
     249    25945000 :         *start = *step < 0 ? PY_SSIZE_T_MAX : 0;
     250             :     }
     251             :     else {
     252    22894400 :         if (!_PyEval_SliceIndex(r->start, start)) return -1;
     253             :     }
     254             : 
     255    48839300 :     if (r->stop == Py_None) {
     256    12395200 :         *stop = *step < 0 ? PY_SSIZE_T_MIN : PY_SSIZE_T_MAX;
     257             :     }
     258             :     else {
     259    36444100 :         if (!_PyEval_SliceIndex(r->stop, stop)) return -1;
     260             :     }
     261             : 
     262    48839300 :     return 0;
     263             : }
     264             : 
     265             : Py_ssize_t
     266    48839300 : 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    48839300 :     assert(step != 0);
     272    48839300 :     assert(step >= -PY_SSIZE_T_MAX);
     273             : 
     274    48839300 :     if (*start < 0) {
     275      891720 :         *start += length;
     276      891720 :         if (*start < 0) {
     277       26067 :             *start = (step < 0) ? -1 : 0;
     278             :         }
     279             :     }
     280    47947600 :     else if (*start >= length) {
     281     5296890 :         *start = (step < 0) ? length - 1 : length;
     282             :     }
     283             : 
     284    48839300 :     if (*stop < 0) {
     285      722676 :         *stop += length;
     286      722676 :         if (*stop < 0) {
     287      141363 :             *stop = (step < 0) ? -1 : 0;
     288             :         }
     289             :     }
     290    48116600 :     else if (*stop >= length) {
     291    24075800 :         *stop = (step < 0) ? length - 1 : length;
     292             :     }
     293             : 
     294    48839300 :     if (step < 0) {
     295      169192 :         if (*stop < *start) {
     296      138917 :             return (*start - *stop - 1) / (-step) + 1;
     297             :         }
     298             :     }
     299             :     else {
     300    48670100 :         if (*start < *stop) {
     301    43280200 :             return (*stop - *start - 1) / step + 1;
     302             :         }
     303             :     }
     304     5420180 :     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        8295 : slice_new(PyTypeObject *type, PyObject *args, PyObject *kw)
     322             : {
     323             :     PyObject *start, *stop, *step;
     324             : 
     325        8295 :     start = stop = step = NULL;
     326             : 
     327        8295 :     if (!_PyArg_NoKeywords("slice", kw))
     328           0 :         return NULL;
     329             : 
     330        8295 :     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        8293 :     if (stop == NULL) {
     336          32 :         stop = start;
     337          32 :         start = NULL;
     338             :     }
     339        8293 :     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    49051500 : slice_dealloc(PySliceObject *r)
     350             : {
     351    49051500 :     PyInterpreterState *interp = _PyInterpreterState_GET();
     352    49051500 :     _PyObject_GC_UNTRACK(r);
     353    49051500 :     Py_DECREF(r->step);
     354    49051500 :     Py_DECREF(r->start);
     355    49051500 :     Py_DECREF(r->stop);
     356    49051500 :     if (interp->slice_cache == NULL) {
     357    49050400 :         interp->slice_cache = r;
     358             :     }
     359             :     else {
     360        1191 :         PyObject_GC_Del(r);
     361             :     }
     362    49051500 : }
     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      338701 : evaluate_slice_index(PyObject *v)
     382             : {
     383      338701 :     if (_PyIndex_Check(v)) {
     384      338698 :         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      279183 : _PySlice_GetLongIndices(PySliceObject *self, PyObject *length,
     400             :                         PyObject **start_ptr, PyObject **stop_ptr,
     401             :                         PyObject **step_ptr)
     402             : {
     403      279183 :     PyObject *start=NULL, *stop=NULL, *step=NULL;
     404      279183 :     PyObject *upper=NULL, *lower=NULL;
     405             :     int step_is_negative, cmp_result;
     406             : 
     407             :     /* Convert step to an integer; raise for zero step. */
     408      279183 :     if (self->step == Py_None) {
     409        3448 :         step = _PyLong_GetOne();
     410        3448 :         Py_INCREF(step);
     411        3448 :         step_is_negative = 0;
     412             :     }
     413             :     else {
     414             :         int step_sign;
     415      275735 :         step = evaluate_slice_index(self->step);
     416      275735 :         if (step == NULL)
     417           1 :             goto error;
     418      275734 :         step_sign = _PyLong_Sign(step);
     419      275734 :         if (step_sign == 0) {
     420         865 :             PyErr_SetString(PyExc_ValueError,
     421             :                             "slice step cannot be zero");
     422         865 :             goto error;
     423             :         }
     424      274869 :         step_is_negative = step_sign < 0;
     425             :     }
     426             : 
     427             :     /* Find lower and upper bounds for start and stop. */
     428      278317 :     if (step_is_negative) {
     429      259274 :         lower = PyLong_FromLong(-1L);
     430      259274 :         if (lower == NULL)
     431           0 :             goto error;
     432             : 
     433      259274 :         upper = PyNumber_Add(length, lower);
     434      259274 :         if (upper == NULL)
     435           0 :             goto error;
     436             :     }
     437             :     else {
     438       19043 :         lower = _PyLong_GetZero();
     439       19043 :         Py_INCREF(lower);
     440       19043 :         upper = length;
     441       19043 :         Py_INCREF(upper);
     442             :     }
     443             : 
     444             :     /* Compute start. */
     445      278317 :     if (self->start == Py_None) {
     446      246846 :         start = step_is_negative ? upper : lower;
     447      246846 :         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      278316 :     if (self->stop == Py_None) {
     485      246821 :         stop = step_is_negative ? lower : upper;
     486      246821 :         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      278311 :     *start_ptr = start;
     523      278311 :     *stop_ptr = stop;
     524      278311 :     *step_ptr = step;
     525      278311 :     Py_DECREF(upper);
     526      278311 :     Py_DECREF(lower);
     527      278311 :     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       20397 : 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       20397 :     length = PyNumber_Index(len);
     550       20397 :     if (length == NULL)
     551           1 :         return NULL;
     552             : 
     553       20396 :     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       20394 :     error = _PySlice_GetLongIndices(self, length, &start, &stop, &step);
     561       20394 :     Py_DECREF(length);
     562       20394 :     if (error == -1)
     563         870 :         return NULL;
     564             :     else
     565       19524 :         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        7080 : slice_traverse(PySliceObject *v, visitproc visit, void *arg)
     642             : {
     643        7080 :     Py_VISIT(v->start);
     644        7080 :     Py_VISIT(v->stop);
     645        7080 :     Py_VISIT(v->step);
     646        7080 :     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