diff -r 14f042958c32 Include/sliceobject.h --- a/Include/sliceobject.h Tue Aug 30 02:12:43 2016 -0500 +++ b/Include/sliceobject.h Tue Aug 30 20:41:26 2016 +0300 @@ -40,9 +40,18 @@ PyAPI_FUNC(int) _PySlice_GetLongIndices( #endif PyAPI_FUNC(int) PySlice_GetIndices(PyObject *r, Py_ssize_t length, Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step); +PyAPI_FUNC(int) _PySlice_Unpack(PyObject *r, + Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step); +PyAPI_FUNC(int) _PySlice_EvalIndices(Py_ssize_t *start, Py_ssize_t *stop, + Py_ssize_t step, Py_ssize_t length, + Py_ssize_t *slicelength); PyAPI_FUNC(int) PySlice_GetIndicesEx(PyObject *r, Py_ssize_t length, - Py_ssize_t *start, Py_ssize_t *stop, - Py_ssize_t *step, Py_ssize_t *slicelength); + Py_ssize_t *start, Py_ssize_t *stop, + Py_ssize_t *step, Py_ssize_t *slicelength); +#define PySlice_GetIndicesEx(r, length, start, stop, step, slicelength) ( \ + _PySlice_Unpack((r), (start), (stop), (step)) < 0 || \ + _PySlice_EvalIndices((start), (stop), *(step), (length), (slicelen)) < 0 ? \ + -1 : 0) #ifdef __cplusplus } diff -r 14f042958c32 Objects/sliceobject.c --- a/Objects/sliceobject.c Tue Aug 30 02:12:43 2016 -0500 +++ b/Objects/sliceobject.c Tue Aug 30 20:41:26 2016 +0300 @@ -191,15 +191,12 @@ PySlice_GetIndices(PyObject *_r, Py_ssiz } int -PySlice_GetIndicesEx(PyObject *_r, Py_ssize_t length, - Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step, - Py_ssize_t *slicelength) +_PySlice_Unpack(PyObject *_r, + Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step) { PySliceObject *r = (PySliceObject*)_r; /* this is harder to get right than you might think */ - Py_ssize_t defstart, defstop; - if (r->step == Py_None) { *step = 1; } @@ -219,45 +216,78 @@ PySlice_GetIndicesEx(PyObject *_r, Py_ss *step = -PY_SSIZE_T_MAX; } - defstart = *step < 0 ? length-1 : 0; - defstop = *step < 0 ? -1 : length; - if (r->start == Py_None) { - *start = defstart; + *start = *step < 0 ? PY_SSIZE_T_MAX-1 : 0;; } 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) - *start = (*step < 0) ? length - 1 : length; } if (r->stop == Py_None) { - *stop = defstop; + *stop = *step < 0 ? -PY_SSIZE_T_MAX : PY_SSIZE_T_MAX; } 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) - *stop = (*step < 0) ? length - 1 : length; - } - - if ((*step < 0 && *stop >= *start) - || (*step > 0 && *start >= *stop)) { - *slicelength = 0; - } - else if (*step < 0) { - *slicelength = (*stop-*start+1)/(*step)+1; - } - else { - *slicelength = (*stop-*start-1)/(*step)+1; } return 0; } +int +_PySlice_EvalIndices(Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t step, Py_ssize_t length, + Py_ssize_t *slicelength) +{ + /* this is harder to get right than you might think */ + + assert(step != 0); + assert(step >= -PY_SSIZE_T_MAX); + + if (*start < 0) { + *start += length; + if (*start < 0) { + *start = (step < 0) ? -1 : 0; + } + } + else if (*start >= length) { + *start = (step < 0) ? length - 1 : length; + } + + if (*stop < 0) { + *stop += length; + if (*stop < 0) { + *stop = (step < 0) ? -1 : 0; + } + } + else if (*stop >= length) { + *stop = (step < 0) ? length - 1 : length; + } + + if ((step < 0 && *stop >= *start) + || (step > 0 && *start >= *stop)) { + *slicelength = 0; + } + else if (step < 0) { + *slicelength = (*stop-*start+1)/step+1; + } + else { + *slicelength = (*stop-*start-1)/step+1; + } + + return 0; +} + +#undef PySlice_GetIndicesEx + +int +PySlice_GetIndicesEx(PyObject *_r, Py_ssize_t length, + Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step, + Py_ssize_t *slicelength) +{ + if (_PySlice_Unpack(_r, start, stop, step) < 0) + return -1; + return _PySlice_EvalIndices(start, stop, *step, length, slicelength); +} + static PyObject * slice_new(PyTypeObject *type, PyObject *args, PyObject *kw) {