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