Skip to content

Commit 3efe32e

Browse files
Issue python#27867: Replaced function PySlice_GetIndicesEx() with a macro.
1 parent efba28c commit 3efe32e

File tree

3 files changed

+70
-23
lines changed

3 files changed

+70
-23
lines changed

Include/sliceobject.h

+10
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,16 @@ PyAPI_FUNC(int) PySlice_GetIndicesEx(PySliceObject *r, Py_ssize_t length,
3838
Py_ssize_t *start, Py_ssize_t *stop,
3939
Py_ssize_t *step, Py_ssize_t *slicelength);
4040

41+
#define PySlice_GetIndicesEx(slice, length, start, stop, step, slicelen) ( \
42+
_PySlice_Unpack((PyObject *)(slice), (start), (stop), (step)) < 0 ? -1 : \
43+
((*slicelen = _PySlice_AdjustIndices((length), (start), (stop), *(step))), \
44+
0))
45+
PyAPI_FUNC(int) _PySlice_Unpack(PyObject *slice,
46+
Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step);
47+
PyAPI_FUNC(Py_ssize_t) _PySlice_AdjustIndices(Py_ssize_t length,
48+
Py_ssize_t *start, Py_ssize_t *stop,
49+
Py_ssize_t step);
50+
4151
#ifdef __cplusplus
4252
}
4353
#endif

Misc/NEWS

+5
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@ Library
6868
- Issue #28925: cPickle now correctly propagates errors when unpickle instances
6969
of old-style classes.
7070

71+
C API
72+
-----
73+
74+
- Issue #27867: Function PySlice_GetIndicesEx() is replaced with a macro.
75+
7176
Build
7277
-----
7378

Objects/sliceobject.c

+55-23
Original file line numberDiff line numberDiff line change
@@ -131,13 +131,12 @@ PySlice_GetIndices(PySliceObject *r, Py_ssize_t length,
131131
}
132132

133133
int
134-
PySlice_GetIndicesEx(PySliceObject *r, Py_ssize_t length,
135-
Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step, Py_ssize_t *slicelength)
134+
_PySlice_Unpack(PyObject *_r,
135+
Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step)
136136
{
137+
PySliceObject *r = (PySliceObject *)_r;
137138
/* this is harder to get right than you might think */
138139

139-
Py_ssize_t defstart, defstop;
140-
141140
if (r->step == Py_None) {
142141
*step = 1;
143142
}
@@ -150,42 +149,75 @@ PySlice_GetIndicesEx(PySliceObject *r, Py_ssize_t length,
150149
}
151150
}
152151

153-
defstart = *step < 0 ? length-1 : 0;
154-
defstop = *step < 0 ? -1 : length;
155-
156152
if (r->start == Py_None) {
157-
*start = defstart;
153+
*start = *step < 0 ? PY_SSIZE_T_MAX-1 : 0;;
158154
}
159155
else {
160156
if (!_PyEval_SliceIndex(r->start, start)) return -1;
161-
if (*start < 0) *start += length;
162-
if (*start < 0) *start = (*step < 0) ? -1 : 0;
163-
if (*start >= length)
164-
*start = (*step < 0) ? length - 1 : length;
165157
}
166158

167159
if (r->stop == Py_None) {
168-
*stop = defstop;
160+
*stop = *step < 0 ? -PY_SSIZE_T_MAX : PY_SSIZE_T_MAX;
169161
}
170162
else {
171163
if (!_PyEval_SliceIndex(r->stop, stop)) return -1;
172-
if (*stop < 0) *stop += length;
173-
if (*stop < 0) *stop = (*step < 0) ? -1 : 0;
174-
if (*stop >= length)
175-
*stop = (*step < 0) ? length - 1 : length;
176164
}
177165

178-
if ((*step < 0 && *stop >= *start)
179-
|| (*step > 0 && *start >= *stop)) {
180-
*slicelength = 0;
166+
return 0;
167+
}
168+
169+
Py_ssize_t
170+
_PySlice_AdjustIndices(Py_ssize_t length,
171+
Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t step)
172+
{
173+
/* this is harder to get right than you might think */
174+
175+
assert(step != 0);
176+
assert(step >= -PY_SSIZE_T_MAX);
177+
178+
if (*start < 0) {
179+
*start += length;
180+
if (*start < 0) {
181+
*start = (step < 0) ? -1 : 0;
182+
}
181183
}
182-
else if (*step < 0) {
183-
*slicelength = (*stop-*start+1)/(*step)+1;
184+
else if (*start >= length) {
185+
*start = (step < 0) ? length - 1 : length;
186+
}
187+
188+
if (*stop < 0) {
189+
*stop += length;
190+
if (*stop < 0) {
191+
*stop = (step < 0) ? -1 : 0;
192+
}
193+
}
194+
else if (*stop >= length) {
195+
*stop = (step < 0) ? length - 1 : length;
196+
}
197+
198+
if (step < 0) {
199+
if (*stop < *start) {
200+
return (*start - *stop - 1) / (-step) + 1;
201+
}
184202
}
185203
else {
186-
*slicelength = (*stop-*start-1)/(*step)+1;
204+
if (*start < *stop) {
205+
return (*stop - *start - 1) / step + 1;
206+
}
187207
}
208+
return 0;
209+
}
210+
211+
#undef PySlice_GetIndicesEx
188212

213+
int
214+
PySlice_GetIndicesEx(PySliceObject *r, Py_ssize_t length,
215+
Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step,
216+
Py_ssize_t *slicelength)
217+
{
218+
if (_PySlice_Unpack((PyObject *)r, start, stop, step) < 0)
219+
return -1;
220+
*slicelength = _PySlice_AdjustIndices(length, start, stop, *step);
189221
return 0;
190222
}
191223

0 commit comments

Comments
 (0)