# HG changeset patch # Parent 19b2c54e5f093f6a345aa82b54c5295688c22790 diff -r 19b2c54e5f09 Include/sliceobject.h --- a/Include/sliceobject.h Wed Nov 12 10:23:44 2014 -0500 +++ b/Include/sliceobject.h Sun Nov 16 09:14:02 2014 +0100 @@ -22,6 +22,8 @@ typedef struct { PyObject_HEAD PyObject *start, *stop, *step; /* not NULL */ + Py_ssize_t istart, istop, istep; + int flags; } PySliceObject; #endif @@ -33,6 +35,7 @@ PyAPI_FUNC(PyObject *) PySlice_New(PyObject* start, PyObject* stop, PyObject* step); #ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) PySlice_FromIndices(Py_ssize_t start, Py_ssize_t stop, Py_ssize_t step); PyAPI_FUNC(PyObject *) _PySlice_FromIndices(Py_ssize_t start, Py_ssize_t stop); PyAPI_FUNC(int) _PySlice_GetLongIndices(PySliceObject *self, PyObject *length, PyObject **start_ptr, PyObject **stop_ptr, diff -r 19b2c54e5f09 Objects/sliceobject.c --- a/Objects/sliceobject.c Wed Nov 12 10:23:44 2014 -0500 +++ b/Objects/sliceobject.c Sun Nov 16 09:14:02 2014 +0100 @@ -93,6 +93,10 @@ /* Slice object implementation */ +#define ISTART_OK 1 +#define ISTOP_OK 2 +#define ISTEP_OK 4 + /* Using a cache is very effective since typically only a single slice is * created and then deleted again */ @@ -114,6 +118,7 @@ PySlice_New(PyObject *start, PyObject *stop, PyObject *step) { PySliceObject *obj; + int flags = 0; if (slice_cache != NULL) { obj = slice_cache; slice_cache = NULL; @@ -124,9 +129,15 @@ return NULL; } - if (step == NULL) step = Py_None; + if (step == NULL || step == Py_None) { + step = Py_None; + flags |= ISTEP_OK; + } Py_INCREF(step); - if (start == NULL) start = Py_None; + if (start == NULL || start == Py_None) { + start = Py_None; + flags |= ISTART_OK; + } Py_INCREF(start); if (stop == NULL) stop = Py_None; Py_INCREF(stop); @@ -134,6 +145,9 @@ obj->step = step; obj->start = start; obj->stop = stop; + obj->istart = 0; + obj->istep = 1; + obj->flags = flags; return (PyObject *) obj; } @@ -141,7 +155,20 @@ PyObject * _PySlice_FromIndices(Py_ssize_t istart, Py_ssize_t istop) { - PyObject *start, *end, *slice; + return PySlice_FromIndices(istart, istop, 1); +} + +PyObject * +PySlice_FromIndices(Py_ssize_t istart, Py_ssize_t istop, Py_ssize_t istep) +{ + PySliceObject *slobj; + PyObject *start, *end, *step, *slice; + if (istep == 0) { + PyErr_SetString(PyExc_ValueError, + "slice step cannot be zero"); + return NULL; + } + start = PyLong_FromSsize_t(istart); if (!start) return NULL; @@ -150,10 +177,28 @@ Py_DECREF(start); return NULL; } + if (istep == 1) { + step = Py_None; + Py_INCREF(step); + } + else { + step = PyLong_FromSsize_t(istep); + if (!step) { + Py_DECREF(start); + Py_DECREF(end); + return NULL; + } + } - slice = PySlice_New(start, end, NULL); + slice = PySlice_New(start, end, step); Py_DECREF(start); Py_DECREF(end); + Py_DECREF(step); + slobj = (PySliceObject*) slice; + slobj->istart = istart; + slobj->istop = istop; + slobj->istep = istep; + slobj->flags = ISTART_OK | ISTOP_OK | ISTEP_OK; return slice; } @@ -203,7 +248,15 @@ *step = 1; } else { - if (!_PyEval_SliceIndex(r->step, step)) return -1; + if (r->flags & ISTEP_OK) { +#ifdef Py_DEBUG + if (!_PyEval_SliceIndex(r->step, step)) return -1; + assert(*step == r->istep); +#endif + *step = r->istep; + } else { + if (!_PyEval_SliceIndex(r->step, step)) return -1; + } if (*step == 0) { PyErr_SetString(PyExc_ValueError, "slice step cannot be zero"); @@ -225,7 +278,15 @@ *start = defstart; } else { - if (!_PyEval_SliceIndex(r->start, start)) return -1; + if (r->flags & ISTART_OK) { +#ifdef Py_DEBUG + if (!_PyEval_SliceIndex(r->start, start)) return -1; + assert(*start == r->istart); +#endif + *start = r->istart; + } else { + if (!_PyEval_SliceIndex(r->start, start)) return -1; + } if (*start < 0) *start += length; if (*start < 0) *start = (*step < 0) ? -1 : 0; if (*start >= length) @@ -236,7 +297,15 @@ *stop = defstop; } else { - if (!_PyEval_SliceIndex(r->stop, stop)) return -1; + if (r->flags & ISTOP_OK) { +#ifdef Py_DEBUG + if (!_PyEval_SliceIndex(r->stop, stop)) return -1; + assert(*stop == r->istop); +#endif + *stop = r->istop; + } else { + if (!_PyEval_SliceIndex(r->stop, stop)) return -1; + } if (*stop < 0) *stop += length; if (*stop < 0) *stop = (*step < 0) ? -1 : 0; if (*stop >= length)