[Python-checkins] cpython (2.7): Issue #27867: Replaced function PySlice_GetIndicesEx() with a macro.

serhiy.storchaka python-checkins at python.org
Wed Jan 25 06:29:16 EST 2017


https://hg.python.org/cpython/rev/d5590f357d74
changeset:   106311:d5590f357d74
branch:      2.7
parent:      106292:fb2885f9b4dd
user:        Serhiy Storchaka <storchaka at gmail.com>
date:        Wed Jan 25 13:22:06 2017 +0200
summary:
  Issue #27867: Replaced function PySlice_GetIndicesEx() with a macro.

files:
  Include/sliceobject.h |  10 +++
  Misc/NEWS             |   5 +
  Objects/sliceobject.c |  78 +++++++++++++++++++++---------
  3 files changed, 70 insertions(+), 23 deletions(-)


diff --git a/Include/sliceobject.h b/Include/sliceobject.h
--- a/Include/sliceobject.h
+++ b/Include/sliceobject.h
@@ -38,6 +38,16 @@
 				    Py_ssize_t *start, Py_ssize_t *stop, 
 				    Py_ssize_t *step, Py_ssize_t *slicelength);
 
+#define PySlice_GetIndicesEx(slice, length, start, stop, step, slicelen) (  \
+    _PySlice_Unpack((PyObject *)(slice), (start), (stop), (step)) < 0 ? -1 :  \
+    ((*slicelen = _PySlice_AdjustIndices((length), (start), (stop), *(step))), \
+     0))
+PyAPI_FUNC(int) _PySlice_Unpack(PyObject *slice,
+                                Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step);
+PyAPI_FUNC(Py_ssize_t) _PySlice_AdjustIndices(Py_ssize_t length,
+                                              Py_ssize_t *start, Py_ssize_t *stop,
+                                              Py_ssize_t step);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -68,6 +68,11 @@
 - Issue #28925: cPickle now correctly propagates errors when unpickle instances
   of old-style classes.
 
+C API
+-----
+
+- Issue #27867: Function PySlice_GetIndicesEx() is replaced with a macro.
+
 Build
 -----
 
diff --git a/Objects/sliceobject.c b/Objects/sliceobject.c
--- a/Objects/sliceobject.c
+++ b/Objects/sliceobject.c
@@ -131,13 +131,12 @@
 }
 
 int
-PySlice_GetIndicesEx(PySliceObject *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;
     }
@@ -150,42 +149,75 @@
         }
     }
 
-    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;
+    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 (*step < 0) {
-        *slicelength = (*stop-*start+1)/(*step)+1;
+    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 {
-        *slicelength = (*stop-*start-1)/(*step)+1;
+        if (*start < *stop) {
+            return (*stop - *start - 1) / step + 1;
+        }
     }
+    return 0;
+}
 
+#undef PySlice_GetIndicesEx
+
+int
+PySlice_GetIndicesEx(PySliceObject *r, Py_ssize_t length,
+                     Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step,
+                     Py_ssize_t *slicelength)
+{
+    if (_PySlice_Unpack((PyObject *)r, start, stop, step) < 0)
+        return -1;
+    *slicelength = _PySlice_AdjustIndices(length, start, stop, *step);
     return 0;
 }
 

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list