LCOV - code coverage report
Current view: top level - libreoffice/workdir/unxlngi6.pro/UnpackedTarball/python3/Objects - sliceobject.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 59 160 36.9 %
Date: 2012-12-17 Functions: 4 13 30.8 %
Legend: Lines: hit not hit

          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 "structmember.h"
      18             : 
      19             : static PyObject *
      20           0 : ellipsis_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
      21             : {
      22           0 :     if (PyTuple_GET_SIZE(args) || (kwargs && PyDict_Size(kwargs))) {
      23           0 :         PyErr_SetString(PyExc_TypeError, "EllipsisType takes no arguments");
      24           0 :         return NULL;
      25             :     }
      26           0 :     Py_INCREF(Py_Ellipsis);
      27           0 :     return Py_Ellipsis;
      28             : }
      29             : 
      30             : static PyObject *
      31           0 : ellipsis_repr(PyObject *op)
      32             : {
      33           0 :     return PyUnicode_FromString("Ellipsis");
      34             : }
      35             : 
      36             : PyTypeObject PyEllipsis_Type = {
      37             :     PyVarObject_HEAD_INIT(&PyType_Type, 0)
      38             :     "ellipsis",                         /* tp_name */
      39             :     0,                                  /* tp_basicsize */
      40             :     0,                                  /* tp_itemsize */
      41             :     0, /*never called*/                 /* tp_dealloc */
      42             :     0,                                  /* tp_print */
      43             :     0,                                  /* tp_getattr */
      44             :     0,                                  /* tp_setattr */
      45             :     0,                                  /* tp_reserved */
      46             :     ellipsis_repr,                      /* tp_repr */
      47             :     0,                                  /* tp_as_number */
      48             :     0,                                  /* tp_as_sequence */
      49             :     0,                                  /* tp_as_mapping */
      50             :     0,                                  /* tp_hash */
      51             :     0,                                  /* tp_call */
      52             :     0,                                  /* tp_str */
      53             :     PyObject_GenericGetAttr,            /* tp_getattro */
      54             :     0,                                  /* tp_setattro */
      55             :     0,                                  /* tp_as_buffer */
      56             :     Py_TPFLAGS_DEFAULT,                 /* tp_flags */
      57             :     0,                                  /* tp_doc */
      58             :     0,                                  /* tp_traverse */
      59             :     0,                                  /* tp_clear */
      60             :     0,                                  /* tp_richcompare */
      61             :     0,                                  /* tp_weaklistoffset */
      62             :     0,                                  /* tp_iter */
      63             :     0,                                  /* tp_iternext */
      64             :     0,                                  /* tp_methods */
      65             :     0,                                  /* tp_members */
      66             :     0,                                  /* tp_getset */
      67             :     0,                                  /* tp_base */
      68             :     0,                                  /* tp_dict */
      69             :     0,                                  /* tp_descr_get */
      70             :     0,                                  /* tp_descr_set */
      71             :     0,                                  /* tp_dictoffset */
      72             :     0,                                  /* tp_init */
      73             :     0,                                  /* tp_alloc */
      74             :     ellipsis_new,                       /* tp_new */
      75             : };
      76             : 
      77             : PyObject _Py_EllipsisObject = {
      78             :     _PyObject_EXTRA_INIT
      79             :     1, &PyEllipsis_Type
      80             : };
      81             : 
      82             : 
      83             : /* Slice object implementation */
      84             : 
      85             : /* Using a cache is very effective since typically only a single slice is
      86             :  * created and then deleted again
      87             :  */
      88             : static PySliceObject *slice_cache = NULL;
      89           0 : void PySlice_Fini(void)
      90             : {
      91           0 :     PySliceObject *obj = slice_cache;
      92           0 :     if (obj != NULL) {
      93           0 :         slice_cache = NULL;
      94           0 :         PyObject_Del(obj);
      95             :     }
      96           0 : }
      97             : 
      98             : /* start, stop, and step are python objects with None indicating no
      99             :    index is present.
     100             : */
     101             : 
     102             : PyObject *
     103       16393 : PySlice_New(PyObject *start, PyObject *stop, PyObject *step)
     104             : {
     105             :     PySliceObject *obj;
     106       16393 :     if (slice_cache != NULL) {
     107       16392 :         obj = slice_cache;
     108       16392 :         slice_cache = NULL;
     109       16392 :         _Py_NewReference((PyObject *)obj);
     110             :     } else {
     111           1 :         obj = PyObject_New(PySliceObject, &PySlice_Type);
     112           1 :         if (obj == NULL)
     113           0 :             return NULL;
     114             :     }
     115             : 
     116       16393 :     if (step == NULL) step = Py_None;
     117       16393 :     Py_INCREF(step);
     118       16393 :     if (start == NULL) start = Py_None;
     119       16393 :     Py_INCREF(start);
     120       16393 :     if (stop == NULL) stop = Py_None;
     121       16393 :     Py_INCREF(stop);
     122             : 
     123       16393 :     obj->step = step;
     124       16393 :     obj->start = start;
     125       16393 :     obj->stop = stop;
     126             : 
     127       16393 :     return (PyObject *) obj;
     128             : }
     129             : 
     130             : PyObject *
     131          18 : _PySlice_FromIndices(Py_ssize_t istart, Py_ssize_t istop)
     132             : {
     133             :     PyObject *start, *end, *slice;
     134          18 :     start = PyLong_FromSsize_t(istart);
     135          18 :     if (!start)
     136           0 :         return NULL;
     137          18 :     end = PyLong_FromSsize_t(istop);
     138          18 :     if (!end) {
     139           0 :         Py_DECREF(start);
     140           0 :         return NULL;
     141             :     }
     142             : 
     143          18 :     slice = PySlice_New(start, end, NULL);
     144          18 :     Py_DECREF(start);
     145          18 :     Py_DECREF(end);
     146          18 :     return slice;
     147             : }
     148             : 
     149             : int
     150           0 : PySlice_GetIndices(PyObject *_r, Py_ssize_t length,
     151             :                    Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step)
     152             : {
     153           0 :     PySliceObject *r = (PySliceObject*)_r;
     154             :     /* XXX support long ints */
     155           0 :     if (r->step == Py_None) {
     156           0 :         *step = 1;
     157             :     } else {
     158           0 :         if (!PyLong_Check(r->step)) return -1;
     159           0 :         *step = PyLong_AsSsize_t(r->step);
     160             :     }
     161           0 :     if (r->start == Py_None) {
     162           0 :         *start = *step < 0 ? length-1 : 0;
     163             :     } else {
     164           0 :         if (!PyLong_Check(r->start)) return -1;
     165           0 :         *start = PyLong_AsSsize_t(r->start);
     166           0 :         if (*start < 0) *start += length;
     167             :     }
     168           0 :     if (r->stop == Py_None) {
     169           0 :         *stop = *step < 0 ? -1 : length;
     170             :     } else {
     171           0 :         if (!PyLong_Check(r->stop)) return -1;
     172           0 :         *stop = PyLong_AsSsize_t(r->stop);
     173           0 :         if (*stop < 0) *stop += length;
     174             :     }
     175           0 :     if (*stop > length) return -1;
     176           0 :     if (*start >= length) return -1;
     177           0 :     if (*step == 0) return -1;
     178           0 :     return 0;
     179             : }
     180             : 
     181             : int
     182       16393 : PySlice_GetIndicesEx(PyObject *_r, Py_ssize_t length,
     183             :                      Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step,
     184             :                      Py_ssize_t *slicelength)
     185             : {
     186       16393 :     PySliceObject *r = (PySliceObject*)_r;
     187             :     /* this is harder to get right than you might think */
     188             : 
     189             :     Py_ssize_t defstart, defstop;
     190             : 
     191       16393 :     if (r->step == Py_None) {
     192       16393 :         *step = 1;
     193             :     }
     194             :     else {
     195           0 :         if (!_PyEval_SliceIndex(r->step, step)) return -1;
     196           0 :         if (*step == 0) {
     197           0 :             PyErr_SetString(PyExc_ValueError,
     198             :                             "slice step cannot be zero");
     199           0 :             return -1;
     200             :         }
     201             :         /* Here *step might be -PY_SSIZE_T_MAX-1; in this case we replace it
     202             :          * with -PY_SSIZE_T_MAX.  This doesn't affect the semantics, and it
     203             :          * guards against later undefined behaviour resulting from code that
     204             :          * does "step = -step" as part of a slice reversal.
     205             :          */
     206           0 :         if (*step < -PY_SSIZE_T_MAX)
     207           0 :             *step = -PY_SSIZE_T_MAX;
     208             :     }
     209             : 
     210       16393 :     defstart = *step < 0 ? length-1 : 0;
     211       16393 :     defstop = *step < 0 ? -1 : length;
     212             : 
     213       16393 :     if (r->start == Py_None) {
     214         692 :         *start = defstart;
     215             :     }
     216             :     else {
     217       15701 :         if (!_PyEval_SliceIndex(r->start, start)) return -1;
     218       15701 :         if (*start < 0) *start += length;
     219       15701 :         if (*start < 0) *start = (*step < 0) ? -1 : 0;
     220       15701 :         if (*start >= length)
     221          57 :             *start = (*step < 0) ? length - 1 : length;
     222             :     }
     223             : 
     224       16393 :     if (r->stop == Py_None) {
     225         799 :         *stop = defstop;
     226             :     }
     227             :     else {
     228       15594 :         if (!_PyEval_SliceIndex(r->stop, stop)) return -1;
     229       15594 :         if (*stop < 0) *stop += length;
     230       15594 :         if (*stop < 0) *stop = (*step < 0) ? -1 : 0;
     231       15594 :         if (*stop >= length)
     232         245 :             *stop = (*step < 0) ? length - 1 : length;
     233             :     }
     234             : 
     235       16393 :     if ((*step < 0 && *stop >= *start)
     236       16393 :         || (*step > 0 && *start >= *stop)) {
     237         579 :         *slicelength = 0;
     238             :     }
     239       15814 :     else if (*step < 0) {
     240           0 :         *slicelength = (*stop-*start+1)/(*step)+1;
     241             :     }
     242             :     else {
     243       15814 :         *slicelength = (*stop-*start-1)/(*step)+1;
     244             :     }
     245             : 
     246       16393 :     return 0;
     247             : }
     248             : 
     249             : static PyObject *
     250           0 : slice_new(PyTypeObject *type, PyObject *args, PyObject *kw)
     251             : {
     252             :     PyObject *start, *stop, *step;
     253             : 
     254           0 :     start = stop = step = NULL;
     255             : 
     256           0 :     if (!_PyArg_NoKeywords("slice()", kw))
     257           0 :         return NULL;
     258             : 
     259           0 :     if (!PyArg_UnpackTuple(args, "slice", 1, 3, &start, &stop, &step))
     260           0 :         return NULL;
     261             : 
     262             :     /* This swapping of stop and start is to maintain similarity with
     263             :        range(). */
     264           0 :     if (stop == NULL) {
     265           0 :         stop = start;
     266           0 :         start = NULL;
     267             :     }
     268           0 :     return PySlice_New(start, stop, step);
     269             : }
     270             : 
     271             : PyDoc_STRVAR(slice_doc,
     272             : "slice([start,] stop[, step])\n\
     273             : \n\
     274             : Create a slice object.  This is used for extended slicing (e.g. a[0:10:2]).");
     275             : 
     276             : static void
     277       16393 : slice_dealloc(PySliceObject *r)
     278             : {
     279       16393 :     Py_DECREF(r->step);
     280       16393 :     Py_DECREF(r->start);
     281       16393 :     Py_DECREF(r->stop);
     282       16393 :     if (slice_cache == NULL)
     283       16393 :         slice_cache = r;
     284             :     else
     285           0 :         PyObject_Del(r);
     286       16393 : }
     287             : 
     288             : static PyObject *
     289           0 : slice_repr(PySliceObject *r)
     290             : {
     291           0 :     return PyUnicode_FromFormat("slice(%R, %R, %R)", r->start, r->stop, r->step);
     292             : }
     293             : 
     294             : static PyMemberDef slice_members[] = {
     295             :     {"start", T_OBJECT, offsetof(PySliceObject, start), READONLY},
     296             :     {"stop", T_OBJECT, offsetof(PySliceObject, stop), READONLY},
     297             :     {"step", T_OBJECT, offsetof(PySliceObject, step), READONLY},
     298             :     {0}
     299             : };
     300             : 
     301             : static PyObject*
     302           0 : slice_indices(PySliceObject* self, PyObject* len)
     303             : {
     304             :     Py_ssize_t ilen, start, stop, step, slicelength;
     305             : 
     306           0 :     ilen = PyNumber_AsSsize_t(len, PyExc_OverflowError);
     307             : 
     308           0 :     if (ilen == -1 && PyErr_Occurred()) {
     309           0 :         return NULL;
     310             :     }
     311             : 
     312           0 :     if (PySlice_GetIndicesEx((PyObject*)self, ilen, &start, &stop,
     313             :                              &step, &slicelength) < 0) {
     314           0 :         return NULL;
     315             :     }
     316             : 
     317           0 :     return Py_BuildValue("(nnn)", start, stop, step);
     318             : }
     319             : 
     320             : PyDoc_STRVAR(slice_indices_doc,
     321             : "S.indices(len) -> (start, stop, stride)\n\
     322             : \n\
     323             : Assuming a sequence of length len, calculate the start and stop\n\
     324             : indices, and the stride length of the extended slice described by\n\
     325             : S. Out of bounds indices are clipped in a manner consistent with the\n\
     326             : handling of normal slices.");
     327             : 
     328             : static PyObject *
     329           0 : slice_reduce(PySliceObject* self)
     330             : {
     331           0 :     return Py_BuildValue("O(OOO)", Py_TYPE(self), self->start, self->stop, self->step);
     332             : }
     333             : 
     334             : PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
     335             : 
     336             : static PyMethodDef slice_methods[] = {
     337             :     {"indices",         (PyCFunction)slice_indices,
     338             :      METH_O,            slice_indices_doc},
     339             :     {"__reduce__",      (PyCFunction)slice_reduce,
     340             :      METH_NOARGS,       reduce_doc},
     341             :     {NULL, NULL}
     342             : };
     343             : 
     344             : static PyObject *
     345           0 : slice_richcompare(PyObject *v, PyObject *w, int op)
     346             : {
     347             :     PyObject *t1;
     348             :     PyObject *t2;
     349             :     PyObject *res;
     350             : 
     351           0 :     if (!PySlice_Check(v) || !PySlice_Check(w))
     352           0 :         Py_RETURN_NOTIMPLEMENTED;
     353             : 
     354           0 :     if (v == w) {
     355             :         /* XXX Do we really need this shortcut?
     356             :            There's a unit test for it, but is that fair? */
     357           0 :         switch (op) {
     358             :         case Py_EQ:
     359             :         case Py_LE:
     360             :         case Py_GE:
     361           0 :             res = Py_True;
     362           0 :             break;
     363             :         default:
     364           0 :             res = Py_False;
     365           0 :             break;
     366             :         }
     367           0 :         Py_INCREF(res);
     368           0 :         return res;
     369             :     }
     370             : 
     371           0 :     t1 = PyTuple_New(3);
     372           0 :     if (t1 == NULL)
     373           0 :         return NULL;
     374           0 :     t2 = PyTuple_New(3);
     375           0 :     if (t2 == NULL) {
     376           0 :         Py_DECREF(t1);
     377           0 :         return NULL;
     378             :     }
     379             : 
     380           0 :     PyTuple_SET_ITEM(t1, 0, ((PySliceObject *)v)->start);
     381           0 :     PyTuple_SET_ITEM(t1, 1, ((PySliceObject *)v)->stop);
     382           0 :     PyTuple_SET_ITEM(t1, 2, ((PySliceObject *)v)->step);
     383           0 :     PyTuple_SET_ITEM(t2, 0, ((PySliceObject *)w)->start);
     384           0 :     PyTuple_SET_ITEM(t2, 1, ((PySliceObject *)w)->stop);
     385           0 :     PyTuple_SET_ITEM(t2, 2, ((PySliceObject *)w)->step);
     386             : 
     387           0 :     res = PyObject_RichCompare(t1, t2, op);
     388             : 
     389           0 :     PyTuple_SET_ITEM(t1, 0, NULL);
     390           0 :     PyTuple_SET_ITEM(t1, 1, NULL);
     391           0 :     PyTuple_SET_ITEM(t1, 2, NULL);
     392           0 :     PyTuple_SET_ITEM(t2, 0, NULL);
     393           0 :     PyTuple_SET_ITEM(t2, 1, NULL);
     394           0 :     PyTuple_SET_ITEM(t2, 2, NULL);
     395             : 
     396           0 :     Py_DECREF(t1);
     397           0 :     Py_DECREF(t2);
     398             : 
     399           0 :     return res;
     400             : }
     401             : 
     402             : PyTypeObject PySlice_Type = {
     403             :     PyVarObject_HEAD_INIT(&PyType_Type, 0)
     404             :     "slice",                    /* Name of this type */
     405             :     sizeof(PySliceObject),      /* Basic object size */
     406             :     0,                          /* Item size for varobject */
     407             :     (destructor)slice_dealloc,                  /* tp_dealloc */
     408             :     0,                                          /* tp_print */
     409             :     0,                                          /* tp_getattr */
     410             :     0,                                          /* tp_setattr */
     411             :     0,                                          /* tp_reserved */
     412             :     (reprfunc)slice_repr,                       /* tp_repr */
     413             :     0,                                          /* tp_as_number */
     414             :     0,                                          /* tp_as_sequence */
     415             :     0,                                          /* tp_as_mapping */
     416             :     PyObject_HashNotImplemented,                /* tp_hash */
     417             :     0,                                          /* tp_call */
     418             :     0,                                          /* tp_str */
     419             :     PyObject_GenericGetAttr,                    /* tp_getattro */
     420             :     0,                                          /* tp_setattro */
     421             :     0,                                          /* tp_as_buffer */
     422             :     Py_TPFLAGS_DEFAULT,                         /* tp_flags */
     423             :     slice_doc,                                  /* tp_doc */
     424             :     0,                                          /* tp_traverse */
     425             :     0,                                          /* tp_clear */
     426             :     slice_richcompare,                          /* tp_richcompare */
     427             :     0,                                          /* tp_weaklistoffset */
     428             :     0,                                          /* tp_iter */
     429             :     0,                                          /* tp_iternext */
     430             :     slice_methods,                              /* tp_methods */
     431             :     slice_members,                              /* tp_members */
     432             :     0,                                          /* tp_getset */
     433             :     0,                                          /* tp_base */
     434             :     0,                                          /* tp_dict */
     435             :     0,                                          /* tp_descr_get */
     436             :     0,                                          /* tp_descr_set */
     437             :     0,                                          /* tp_dictoffset */
     438             :     0,                                          /* tp_init */
     439             :     0,                                          /* tp_alloc */
     440             :     slice_new,                                  /* tp_new */
     441             : };

Generated by: LCOV version 1.10