# HG changeset patch # Parent a206f952668e6b3f81d232be25b875bd116938f6 diff -r a206f952668e -r 58d7992e0610 Include/sliceobject.h --- a/Include/sliceobject.h Thu Aug 08 18:28:53 2013 +0100 +++ b/Include/sliceobject.h Fri Aug 23 08:09:28 2013 +0200 @@ -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 a206f952668e -r 58d7992e0610 Objects/sliceobject.c --- a/Objects/sliceobject.c Thu Aug 08 18:28:53 2013 +0100 +++ b/Objects/sliceobject.c Fri Aug 23 08:09:28 2013 +0200 @@ -82,6 +82,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 */ @@ -103,6 +107,7 @@ PySlice_New(PyObject *start, PyObject *stop, PyObject *step) { PySliceObject *obj; + int flags = 0; if (slice_cache != NULL) { obj = slice_cache; slice_cache = NULL; @@ -113,9 +118,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); @@ -123,6 +134,9 @@ obj->step = step; obj->start = start; obj->stop = stop; + obj->istart = 0; + obj->istep = 1; + obj->flags = flags; return (PyObject *) obj; } @@ -130,7 +144,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; @@ -139,10 +166,22 @@ Py_DECREF(start); return NULL; } + 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; } @@ -192,7 +231,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"); @@ -214,7 +261,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) @@ -225,7 +280,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)