Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
ffdb2c21
Commit
ffdb2c21
authored
Nov 17, 2012
by
Mark Dickinson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Issue #16451: Refactor to remove duplication between range and slice in slice index computations.
parent
c3afba10
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
87 additions
and
269 deletions
+87
-269
Include/sliceobject.h
Include/sliceobject.h
+3
-0
Objects/rangeobject.c
Objects/rangeobject.c
+6
-199
Objects/sliceobject.c
Objects/sliceobject.c
+78
-70
No files found.
Include/sliceobject.h
View file @
ffdb2c21
...
@@ -34,6 +34,9 @@ PyAPI_FUNC(PyObject *) PySlice_New(PyObject* start, PyObject* stop,
...
@@ -34,6 +34,9 @@ PyAPI_FUNC(PyObject *) PySlice_New(PyObject* start, PyObject* stop,
PyObject
*
step
);
PyObject
*
step
);
#ifndef Py_LIMITED_API
#ifndef Py_LIMITED_API
PyAPI_FUNC
(
PyObject
*
)
_PySlice_FromIndices
(
Py_ssize_t
start
,
Py_ssize_t
stop
);
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
,
PyObject
**
step_ptr
);
#endif
#endif
PyAPI_FUNC
(
int
)
PySlice_GetIndices
(
PyObject
*
r
,
Py_ssize_t
length
,
PyAPI_FUNC
(
int
)
PySlice_GetIndices
(
PyObject
*
r
,
Py_ssize_t
length
,
Py_ssize_t
*
start
,
Py_ssize_t
*
stop
,
Py_ssize_t
*
step
);
Py_ssize_t
*
start
,
Py_ssize_t
*
stop
,
Py_ssize_t
*
step
);
...
...
Objects/rangeobject.c
View file @
ffdb2c21
...
@@ -318,195 +318,6 @@ range_item(rangeobject *r, Py_ssize_t i)
...
@@ -318,195 +318,6 @@ range_item(rangeobject *r, Py_ssize_t i)
return
res
;
return
res
;
}
}
/* Additional helpers, since the standard slice helpers
* all clip to PY_SSIZE_T_MAX
*/
/* Replace _PyEval_SliceIndex */
static
PyObject
*
compute_slice_element
(
PyObject
*
obj
)
{
PyObject
*
result
=
NULL
;
if
(
obj
!=
NULL
)
{
if
(
PyIndex_Check
(
obj
))
{
result
=
PyNumber_Index
(
obj
);
}
else
{
PyErr_SetString
(
PyExc_TypeError
,
"slice indices must be integers or "
"None or have an __index__ method"
);
}
}
return
result
;
}
/* Replace PySlice_GetIndicesEx
* Result indicates whether or not the slice is empty
* (-1 = error, 0 = empty slice, 1 = slice contains elements)
*/
static
int
compute_slice_indices
(
rangeobject
*
r
,
PySliceObject
*
slice
,
PyObject
**
start
,
PyObject
**
stop
,
PyObject
**
step
)
{
int
cmp_result
,
has_elements
;
Py_ssize_t
clamped_step
=
0
;
PyObject
*
zero
=
NULL
,
*
one
=
NULL
,
*
neg_one
=
NULL
,
*
candidate
=
NULL
;
PyObject
*
tmp_start
=
NULL
,
*
tmp_stop
=
NULL
,
*
tmp_step
=
NULL
;
zero
=
PyLong_FromLong
(
0
);
if
(
zero
==
NULL
)
goto
Fail
;
one
=
PyLong_FromLong
(
1
);
if
(
one
==
NULL
)
goto
Fail
;
neg_one
=
PyLong_FromLong
(
-
1
);
if
(
neg_one
==
NULL
)
goto
Fail
;
/* Calculate step value */
if
(
slice
->
step
==
Py_None
)
{
clamped_step
=
1
;
tmp_step
=
one
;
Py_INCREF
(
tmp_step
);
}
else
{
if
(
!
_PyEval_SliceIndex
(
slice
->
step
,
&
clamped_step
))
goto
Fail
;
if
(
clamped_step
==
0
)
{
PyErr_SetString
(
PyExc_ValueError
,
"slice step cannot be zero"
);
goto
Fail
;
}
tmp_step
=
compute_slice_element
(
slice
->
step
);
if
(
tmp_step
==
NULL
)
goto
Fail
;
}
/* Calculate start value */
if
(
slice
->
start
==
Py_None
)
{
if
(
clamped_step
<
0
)
{
tmp_start
=
PyNumber_Subtract
(
r
->
length
,
one
);
if
(
tmp_start
==
NULL
)
goto
Fail
;
}
else
{
tmp_start
=
zero
;
Py_INCREF
(
tmp_start
);
}
}
else
{
candidate
=
compute_slice_element
(
slice
->
start
);
if
(
candidate
==
NULL
)
goto
Fail
;
cmp_result
=
PyObject_RichCompareBool
(
candidate
,
zero
,
Py_LT
);
if
(
cmp_result
==
-
1
)
goto
Fail
;
if
(
cmp_result
)
{
/* candidate < 0 */
tmp_start
=
PyNumber_Add
(
r
->
length
,
candidate
);
if
(
tmp_start
==
NULL
)
goto
Fail
;
Py_CLEAR
(
candidate
);
}
else
{
/* candidate >= 0 */
tmp_start
=
candidate
;
candidate
=
NULL
;
}
cmp_result
=
PyObject_RichCompareBool
(
tmp_start
,
zero
,
Py_LT
);
if
(
cmp_result
==
-
1
)
goto
Fail
;
if
(
cmp_result
)
{
/* tmp_start < 0 */
Py_CLEAR
(
tmp_start
);
if
(
clamped_step
<
0
)
{
tmp_start
=
neg_one
;
}
else
{
tmp_start
=
zero
;
}
Py_INCREF
(
tmp_start
);
}
else
{
/* tmp_start >= 0 */
cmp_result
=
PyObject_RichCompareBool
(
tmp_start
,
r
->
length
,
Py_GE
);
if
(
cmp_result
==
-
1
)
goto
Fail
;
if
(
cmp_result
)
{
/* tmp_start >= r->length */
Py_CLEAR
(
tmp_start
);
if
(
clamped_step
<
0
)
{
tmp_start
=
PyNumber_Subtract
(
r
->
length
,
one
);
if
(
tmp_start
==
NULL
)
goto
Fail
;
}
else
{
tmp_start
=
r
->
length
;
Py_INCREF
(
tmp_start
);
}
}
}
}
/* Calculate stop value */
if
(
slice
->
stop
==
Py_None
)
{
if
(
clamped_step
<
0
)
{
tmp_stop
=
neg_one
;
}
else
{
tmp_stop
=
r
->
length
;
}
Py_INCREF
(
tmp_stop
);
}
else
{
candidate
=
compute_slice_element
(
slice
->
stop
);
if
(
candidate
==
NULL
)
goto
Fail
;
cmp_result
=
PyObject_RichCompareBool
(
candidate
,
zero
,
Py_LT
);
if
(
cmp_result
==
-
1
)
goto
Fail
;
if
(
cmp_result
)
{
/* candidate < 0 */
tmp_stop
=
PyNumber_Add
(
r
->
length
,
candidate
);
if
(
tmp_stop
==
NULL
)
goto
Fail
;
Py_CLEAR
(
candidate
);
}
else
{
/* candidate >= 0 */
tmp_stop
=
candidate
;
candidate
=
NULL
;
}
cmp_result
=
PyObject_RichCompareBool
(
tmp_stop
,
zero
,
Py_LT
);
if
(
cmp_result
==
-
1
)
goto
Fail
;
if
(
cmp_result
)
{
/* tmp_stop < 0 */
Py_CLEAR
(
tmp_stop
);
if
(
clamped_step
<
0
)
{
tmp_stop
=
neg_one
;
}
else
{
tmp_stop
=
zero
;
}
Py_INCREF
(
tmp_stop
);
}
else
{
/* tmp_stop >= 0 */
cmp_result
=
PyObject_RichCompareBool
(
tmp_stop
,
r
->
length
,
Py_GE
);
if
(
cmp_result
==
-
1
)
goto
Fail
;
if
(
cmp_result
)
{
/* tmp_stop >= r->length */
Py_CLEAR
(
tmp_stop
);
if
(
clamped_step
<
0
)
{
tmp_stop
=
PyNumber_Subtract
(
r
->
length
,
one
);
if
(
tmp_stop
==
NULL
)
goto
Fail
;
}
else
{
tmp_stop
=
r
->
length
;
Py_INCREF
(
tmp_stop
);
}
}
}
}
/* Check if the slice is empty or not */
if
(
clamped_step
<
0
)
{
has_elements
=
PyObject_RichCompareBool
(
tmp_start
,
tmp_stop
,
Py_GT
);
}
else
{
has_elements
=
PyObject_RichCompareBool
(
tmp_start
,
tmp_stop
,
Py_LT
);
}
if
(
has_elements
==
-
1
)
goto
Fail
;
*
start
=
tmp_start
;
*
stop
=
tmp_stop
;
*
step
=
tmp_step
;
Py_DECREF
(
neg_one
);
Py_DECREF
(
one
);
Py_DECREF
(
zero
);
return
has_elements
;
Fail:
Py_XDECREF
(
tmp_start
);
Py_XDECREF
(
tmp_stop
);
Py_XDECREF
(
tmp_step
);
Py_XDECREF
(
candidate
);
Py_XDECREF
(
neg_one
);
Py_XDECREF
(
one
);
Py_XDECREF
(
zero
);
return
-
1
;
}
static
PyObject
*
static
PyObject
*
compute_slice
(
rangeobject
*
r
,
PyObject
*
_slice
)
compute_slice
(
rangeobject
*
r
,
PyObject
*
_slice
)
{
{
...
@@ -514,10 +325,11 @@ compute_slice(rangeobject *r, PyObject *_slice)
...
@@ -514,10 +325,11 @@ compute_slice(rangeobject *r, PyObject *_slice)
rangeobject
*
result
;
rangeobject
*
result
;
PyObject
*
start
=
NULL
,
*
stop
=
NULL
,
*
step
=
NULL
;
PyObject
*
start
=
NULL
,
*
stop
=
NULL
,
*
step
=
NULL
;
PyObject
*
substart
=
NULL
,
*
substop
=
NULL
,
*
substep
=
NULL
;
PyObject
*
substart
=
NULL
,
*
substop
=
NULL
,
*
substep
=
NULL
;
int
has_elements
;
int
error
;
has_elements
=
compute_slice_indices
(
r
,
slice
,
&
start
,
&
stop
,
&
step
);
error
=
_PySlice_GetLongIndices
(
slice
,
r
->
length
,
&
start
,
&
stop
,
&
step
);
if
(
has_elements
==
-
1
)
return
NULL
;
if
(
error
==
-
1
)
return
NULL
;
substep
=
PyNumber_Multiply
(
r
->
step
,
step
);
substep
=
PyNumber_Multiply
(
r
->
step
,
step
);
if
(
substep
==
NULL
)
goto
fail
;
if
(
substep
==
NULL
)
goto
fail
;
...
@@ -527,13 +339,8 @@ compute_slice(rangeobject *r, PyObject *_slice)
...
@@ -527,13 +339,8 @@ compute_slice(rangeobject *r, PyObject *_slice)
if
(
substart
==
NULL
)
goto
fail
;
if
(
substart
==
NULL
)
goto
fail
;
Py_CLEAR
(
start
);
Py_CLEAR
(
start
);
if
(
has_elements
)
{
substop
=
compute_item
(
r
,
stop
);
substop
=
compute_item
(
r
,
stop
);
if
(
substop
==
NULL
)
goto
fail
;
if
(
substop
==
NULL
)
goto
fail
;
}
else
{
substop
=
substart
;
Py_INCREF
(
substop
);
}
Py_CLEAR
(
stop
);
Py_CLEAR
(
stop
);
result
=
make_range_object
(
Py_TYPE
(
r
),
substart
,
substop
,
substep
);
result
=
make_range_object
(
Py_TYPE
(
r
),
substart
,
substop
,
substep
);
...
...
Objects/sliceobject.c
View file @
ffdb2c21
...
@@ -316,57 +316,41 @@ evaluate_slice_index(PyObject *v)
...
@@ -316,57 +316,41 @@ evaluate_slice_index(PyObject *v)
}
}
}
}
/* Implementation of slice.indices. */
/* Compute slice indices given a slice and length. Return -1 on failure. Used
by slice.indices and rangeobject slicing. Assumes that `len` is a
nonnegative instance of PyLong. */
static
PyObject
*
int
slice_indices
(
PySliceObject
*
self
,
PyObject
*
len
)
_PySlice_GetLongIndices
(
PySliceObject
*
self
,
PyObject
*
length
,
PyObject
**
start_ptr
,
PyObject
**
stop_ptr
,
PyObject
**
step_ptr
)
{
{
PyObject
*
start
=
NULL
,
*
stop
=
NULL
,
*
step
=
NULL
;
PyObject
*
start
=
NULL
,
*
stop
=
NULL
,
*
step
=
NULL
;
PyObject
*
length
=
NULL
,
*
upper
=
NULL
,
*
lower
=
NULL
,
*
zero
=
NULL
;
PyObject
*
upper
=
NULL
,
*
lower
=
NULL
;
int
step_is_negative
,
cmp
;
int
step_is_negative
,
cmp_result
;
zero
=
PyLong_FromLong
(
0L
);
if
(
zero
==
NULL
)
return
NULL
;
/* Compute step and length as integers. */
length
=
PyNumber_Index
(
len
);
if
(
length
==
NULL
)
goto
error
;
if
(
self
->
step
==
Py_None
)
/* Convert step to an integer; raise for zero step. */
if
(
self
->
step
==
Py_None
)
{
step
=
PyLong_FromLong
(
1L
);
step
=
PyLong_FromLong
(
1L
);
else
if
(
step
==
NULL
)
step
=
evaluate_slice_index
(
self
->
step
);
goto
error
;
if
(
step
==
NULL
)
step_is_negative
=
0
;
goto
error
;
/* Raise ValueError for negative length or zero step. */
cmp
=
PyObject_RichCompareBool
(
length
,
zero
,
Py_LT
);
if
(
cmp
<
0
)
{
goto
error
;
}
if
(
cmp
)
{
PyErr_SetString
(
PyExc_ValueError
,
"length should not be negative"
);
goto
error
;
}
cmp
=
PyObject_RichCompareBool
(
step
,
zero
,
Py_EQ
);
if
(
cmp
<
0
)
{
goto
error
;
}
}
if
(
cmp
)
{
else
{
PyErr_SetString
(
PyExc_ValueError
,
int
step_sign
;
"slice step cannot be zero"
);
step
=
evaluate_slice_index
(
self
->
step
);
goto
error
;
if
(
step
==
NULL
)
goto
error
;
step_sign
=
_PyLong_Sign
(
step
);
if
(
step_sign
==
0
)
{
PyErr_SetString
(
PyExc_ValueError
,
"slice step cannot be zero"
);
goto
error
;
}
step_is_negative
=
step_sign
<
0
;
}
}
/* Find lower and upper bounds for start and stop. */
/* Find lower and upper bounds for start and stop. */
step_is_negative
=
PyObject_RichCompareBool
(
step
,
zero
,
Py_LT
);
if
(
step_is_negative
<
0
)
{
goto
error
;
}
if
(
step_is_negative
)
{
if
(
step_is_negative
)
{
lower
=
PyLong_FromLong
(
-
1L
);
lower
=
PyLong_FromLong
(
-
1L
);
if
(
lower
==
NULL
)
if
(
lower
==
NULL
)
...
@@ -377,8 +361,10 @@ slice_indices(PySliceObject* self, PyObject* len)
...
@@ -377,8 +361,10 @@ slice_indices(PySliceObject* self, PyObject* len)
goto
error
;
goto
error
;
}
}
else
{
else
{
lower
=
zero
;
lower
=
PyLong_FromLong
(
0L
);
Py_INCREF
(
lower
);
if
(
lower
==
NULL
)
goto
error
;
upper
=
length
;
upper
=
length
;
Py_INCREF
(
upper
);
Py_INCREF
(
upper
);
}
}
...
@@ -393,10 +379,7 @@ slice_indices(PySliceObject* self, PyObject* len)
...
@@ -393,10 +379,7 @@ slice_indices(PySliceObject* self, PyObject* len)
if
(
start
==
NULL
)
if
(
start
==
NULL
)
goto
error
;
goto
error
;
cmp
=
PyObject_RichCompareBool
(
start
,
zero
,
Py_LT
);
if
(
_PyLong_Sign
(
start
)
<
0
)
{
if
(
cmp
<
0
)
goto
error
;
if
(
cmp
)
{
/* start += length */
/* start += length */
PyObject
*
tmp
=
PyNumber_Add
(
start
,
length
);
PyObject
*
tmp
=
PyNumber_Add
(
start
,
length
);
Py_DECREF
(
start
);
Py_DECREF
(
start
);
...
@@ -404,20 +387,20 @@ slice_indices(PySliceObject* self, PyObject* len)
...
@@ -404,20 +387,20 @@ slice_indices(PySliceObject* self, PyObject* len)
if
(
start
==
NULL
)
if
(
start
==
NULL
)
goto
error
;
goto
error
;
cmp
=
PyObject_RichCompareBool
(
start
,
lower
,
Py_LT
);
cmp
_result
=
PyObject_RichCompareBool
(
start
,
lower
,
Py_LT
);
if
(
cmp
<
0
)
if
(
cmp
_result
<
0
)
goto
error
;
goto
error
;
if
(
cmp
)
{
if
(
cmp
_result
)
{
Py_INCREF
(
lower
);
Py_INCREF
(
lower
);
Py_DECREF
(
start
);
Py_DECREF
(
start
);
start
=
lower
;
start
=
lower
;
}
}
}
}
else
{
else
{
cmp
=
PyObject_RichCompareBool
(
start
,
upper
,
Py_GT
);
cmp
_result
=
PyObject_RichCompareBool
(
start
,
upper
,
Py_GT
);
if
(
cmp
<
0
)
if
(
cmp
_result
<
0
)
goto
error
;
goto
error
;
if
(
cmp
)
{
if
(
cmp
_result
)
{
Py_INCREF
(
upper
);
Py_INCREF
(
upper
);
Py_DECREF
(
start
);
Py_DECREF
(
start
);
start
=
upper
;
start
=
upper
;
...
@@ -435,10 +418,7 @@ slice_indices(PySliceObject* self, PyObject* len)
...
@@ -435,10 +418,7 @@ slice_indices(PySliceObject* self, PyObject* len)
if
(
stop
==
NULL
)
if
(
stop
==
NULL
)
goto
error
;
goto
error
;
cmp
=
PyObject_RichCompareBool
(
stop
,
zero
,
Py_LT
);
if
(
_PyLong_Sign
(
stop
)
<
0
)
{
if
(
cmp
<
0
)
goto
error
;
if
(
cmp
)
{
/* stop += length */
/* stop += length */
PyObject
*
tmp
=
PyNumber_Add
(
stop
,
length
);
PyObject
*
tmp
=
PyNumber_Add
(
stop
,
length
);
Py_DECREF
(
stop
);
Py_DECREF
(
stop
);
...
@@ -446,20 +426,20 @@ slice_indices(PySliceObject* self, PyObject* len)
...
@@ -446,20 +426,20 @@ slice_indices(PySliceObject* self, PyObject* len)
if
(
stop
==
NULL
)
if
(
stop
==
NULL
)
goto
error
;
goto
error
;
cmp
=
PyObject_RichCompareBool
(
stop
,
lower
,
Py_LT
);
cmp
_result
=
PyObject_RichCompareBool
(
stop
,
lower
,
Py_LT
);
if
(
cmp
<
0
)
if
(
cmp
_result
<
0
)
goto
error
;
goto
error
;
if
(
cmp
)
{
if
(
cmp
_result
)
{
Py_INCREF
(
lower
);
Py_INCREF
(
lower
);
Py_DECREF
(
stop
);
Py_DECREF
(
stop
);
stop
=
lower
;
stop
=
lower
;
}
}
}
}
else
{
else
{
cmp
=
PyObject_RichCompareBool
(
stop
,
upper
,
Py_GT
);
cmp
_result
=
PyObject_RichCompareBool
(
stop
,
upper
,
Py_GT
);
if
(
cmp
<
0
)
if
(
cmp
_result
<
0
)
goto
error
;
goto
error
;
if
(
cmp
)
{
if
(
cmp
_result
)
{
Py_INCREF
(
upper
);
Py_INCREF
(
upper
);
Py_DECREF
(
stop
);
Py_DECREF
(
stop
);
stop
=
upper
;
stop
=
upper
;
...
@@ -467,23 +447,51 @@ slice_indices(PySliceObject* self, PyObject* len)
...
@@ -467,23 +447,51 @@ slice_indices(PySliceObject* self, PyObject* len)
}
}
}
}
*
start_ptr
=
start
;
*
stop_ptr
=
stop
;
*
step_ptr
=
step
;
Py_DECREF
(
upper
);
Py_DECREF
(
upper
);
Py_DECREF
(
lower
);
Py_DECREF
(
lower
);
Py_DECREF
(
length
);
return
0
;
Py_DECREF
(
zero
);
return
Py_BuildValue
(
"(NNN)"
,
start
,
stop
,
step
);
error:
error:
*
start_ptr
=
*
stop_ptr
=
*
step_ptr
=
NULL
;
Py_XDECREF
(
start
);
Py_XDECREF
(
start
);
Py_XDECREF
(
stop
);
Py_XDECREF
(
stop
);
Py_XDECREF
(
step
);
Py_XDECREF
(
step
);
Py_XDECREF
(
upper
);
Py_XDECREF
(
upper
);
Py_XDECREF
(
lower
);
Py_XDECREF
(
lower
);
Py_XDECREF
(
length
);
return
-
1
;
Py_XDECREF
(
zero
);
return
NULL
;
}
}
/* Implementation of slice.indices. */
static
PyObject
*
slice_indices
(
PySliceObject
*
self
,
PyObject
*
len
)
{
PyObject
*
start
,
*
stop
,
*
step
;
PyObject
*
length
;
int
error
;
/* Convert length to an integer if necessary; raise for negative length. */
length
=
PyNumber_Index
(
len
);
if
(
length
==
NULL
)
return
NULL
;
if
(
_PyLong_Sign
(
length
)
<
0
)
{
PyErr_SetString
(
PyExc_ValueError
,
"length should not be negative"
);
Py_DECREF
(
length
);
return
NULL
;
}
error
=
_PySlice_GetLongIndices
(
self
,
length
,
&
start
,
&
stop
,
&
step
);
Py_DECREF
(
length
);
if
(
error
==
-
1
)
return
NULL
;
else
return
Py_BuildValue
(
"(NNN)"
,
start
,
stop
,
step
);
}
PyDoc_STRVAR
(
slice_indices_doc
,
PyDoc_STRVAR
(
slice_indices_doc
,
"S.indices(len) -> (start, stop, stride)
\n
\
"S.indices(len) -> (start, stop, stride)
\n
\
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment