#include "py27_backports.h" // Provide implementations from python 2.7.15 as backports int _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 */ assert(PY_SSIZE_T_MIN + 1 <= -PY_SSIZE_T_MAX); if (r->step == Py_None) { *step = 1; } else { if (!_PyEval_SliceIndex(r->step, step)) return -1; if (*step == 0) { PyErr_SetString(PyExc_ValueError, "slice step cannot be zero"); return -1; } /* Here *step might be -PY_SSIZE_T_MAX-1; in this case we replace it * with -PY_SSIZE_T_MAX. This doesn't affect the semantics, and it * guards against later undefined behaviour resulting from code that * does "step = -step" as part of a slice reversal. */ if (*step < -PY_SSIZE_T_MAX) *step = -PY_SSIZE_T_MAX; } if (r->start == Py_None) { *start = *step < 0 ? PY_SSIZE_T_MAX : 0; } else { if (!_PyEval_SliceIndex(r->start, start)) return -1; } if (r->stop == Py_None) { *stop = *step < 0 ? PY_SSIZE_T_MIN : PY_SSIZE_T_MAX; } else { if (!_PyEval_SliceIndex(r->stop, stop)) return -1; } return 0; } Py_ssize_t _PySlice_AdjustIndices(Py_ssize_t length, Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t step) { /* 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) { if (*stop < *start) { return (*start - *stop - 1) / (-step) + 1; } } else { if (*start < *stop) { return (*stop - *start - 1) / step + 1; } } return 0; }