py27_backports.c 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. #include "py27_backports.h"
  2. // Provide implementations from python 2.7.15 as backports
  3. int
  4. _PySlice_Unpack(PyObject *_r,
  5. Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step)
  6. {
  7. PySliceObject *r = (PySliceObject *)_r;
  8. /* this is harder to get right than you might think */
  9. assert(PY_SSIZE_T_MIN + 1 <= -PY_SSIZE_T_MAX);
  10. if (r->step == Py_None) {
  11. *step = 1;
  12. }
  13. else {
  14. if (!_PyEval_SliceIndex(r->step, step)) return -1;
  15. if (*step == 0) {
  16. PyErr_SetString(PyExc_ValueError,
  17. "slice step cannot be zero");
  18. return -1;
  19. }
  20. /* Here *step might be -PY_SSIZE_T_MAX-1; in this case we replace it
  21. * with -PY_SSIZE_T_MAX. This doesn't affect the semantics, and it
  22. * guards against later undefined behaviour resulting from code that
  23. * does "step = -step" as part of a slice reversal.
  24. */
  25. if (*step < -PY_SSIZE_T_MAX)
  26. *step = -PY_SSIZE_T_MAX;
  27. }
  28. if (r->start == Py_None) {
  29. *start = *step < 0 ? PY_SSIZE_T_MAX : 0;
  30. }
  31. else {
  32. if (!_PyEval_SliceIndex(r->start, start)) return -1;
  33. }
  34. if (r->stop == Py_None) {
  35. *stop = *step < 0 ? PY_SSIZE_T_MIN : PY_SSIZE_T_MAX;
  36. }
  37. else {
  38. if (!_PyEval_SliceIndex(r->stop, stop)) return -1;
  39. }
  40. return 0;
  41. }
  42. Py_ssize_t
  43. _PySlice_AdjustIndices(Py_ssize_t length,
  44. Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t step)
  45. {
  46. /* this is harder to get right than you might think */
  47. assert(step != 0);
  48. assert(step >= -PY_SSIZE_T_MAX);
  49. if (*start < 0) {
  50. *start += length;
  51. if (*start < 0) {
  52. *start = (step < 0) ? -1 : 0;
  53. }
  54. }
  55. else if (*start >= length) {
  56. *start = (step < 0) ? length - 1 : length;
  57. }
  58. if (*stop < 0) {
  59. *stop += length;
  60. if (*stop < 0) {
  61. *stop = (step < 0) ? -1 : 0;
  62. }
  63. }
  64. else if (*stop >= length) {
  65. *stop = (step < 0) ? length - 1 : length;
  66. }
  67. if (step < 0) {
  68. if (*stop < *start) {
  69. return (*start - *stop - 1) / (-step) + 1;
  70. }
  71. }
  72. else {
  73. if (*start < *stop) {
  74. return (*stop - *start - 1) / step + 1;
  75. }
  76. }
  77. return 0;
  78. }