blob: 02ba033a62a4941178076cb342880e53a1af1e2a [file] [log] [blame]
Guido van Rossumf2d125b1996-07-30 16:45:48 +00001/*
2Written by Jim Hugunin and Chris Chase.
3
Guido van Rossume449af71996-10-11 16:25:41 +00004This includes both the singular ellipsis object and slice objects.
Guido van Rossumf2d125b1996-07-30 16:45:48 +00005
6Guido, feel free to do whatever you want in the way of copyrights
7for this file.
8*/
9
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000010/*
Guido van Rossume449af71996-10-11 16:25:41 +000011Py_Ellipsis encodes the '...' rubber index token. It is similar to
Guido van Rossumf2d125b1996-07-30 16:45:48 +000012the Py_NoneStruct in that there is no way to create other objects of
13this type and there is exactly one in existence.
14*/
15
16#include "Python.h"
Victor Stinner4a21e572020-04-15 02:35:41 +020017#include "pycore_abstract.h" // _PyIndex_Check()
Victor Stinnerc9bc2902020-10-27 02:24:34 +010018#include "pycore_long.h" // _PyLong_GetZero()
Victor Stinner7daba6f2020-06-05 01:14:40 +020019#include "pycore_object.h" // _PyObject_GC_TRACK()
Victor Stinner4a21e572020-04-15 02:35:41 +020020#include "structmember.h" // PyMemberDef
Guido van Rossumf2d125b1996-07-30 16:45:48 +000021
22static PyObject *
Benjamin Petersonc4607ae2011-07-29 18:19:43 -050023ellipsis_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
24{
Serhiy Storchaka5ab81d72016-12-16 16:18:57 +020025 if (PyTuple_GET_SIZE(args) || (kwargs && PyDict_GET_SIZE(kwargs))) {
Benjamin Petersonc4607ae2011-07-29 18:19:43 -050026 PyErr_SetString(PyExc_TypeError, "EllipsisType takes no arguments");
27 return NULL;
28 }
29 Py_INCREF(Py_Ellipsis);
30 return Py_Ellipsis;
31}
32
33static PyObject *
Fred Drake45cfbcc2000-07-09 06:21:27 +000034ellipsis_repr(PyObject *op)
Guido van Rossumf2d125b1996-07-30 16:45:48 +000035{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000036 return PyUnicode_FromString("Ellipsis");
Guido van Rossumf2d125b1996-07-30 16:45:48 +000037}
38
Alexandre Vassalottic49477b2013-11-24 02:53:45 -080039static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +053040ellipsis_reduce(PyObject *op, PyObject *Py_UNUSED(ignored))
Alexandre Vassalottic49477b2013-11-24 02:53:45 -080041{
42 return PyUnicode_FromString("Ellipsis");
43}
44
45static PyMethodDef ellipsis_methods[] = {
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +053046 {"__reduce__", ellipsis_reduce, METH_NOARGS, NULL},
Alexandre Vassalottic49477b2013-11-24 02:53:45 -080047 {NULL, NULL}
48};
49
Benjamin Petersonfd838e62009-04-20 02:09:13 +000050PyTypeObject PyEllipsis_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000051 PyVarObject_HEAD_INIT(&PyType_Type, 0)
52 "ellipsis", /* tp_name */
53 0, /* tp_basicsize */
54 0, /* tp_itemsize */
55 0, /*never called*/ /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +020056 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000057 0, /* tp_getattr */
58 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +020059 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000060 ellipsis_repr, /* tp_repr */
61 0, /* tp_as_number */
62 0, /* tp_as_sequence */
63 0, /* tp_as_mapping */
64 0, /* tp_hash */
65 0, /* tp_call */
66 0, /* tp_str */
67 PyObject_GenericGetAttr, /* tp_getattro */
68 0, /* tp_setattro */
69 0, /* tp_as_buffer */
70 Py_TPFLAGS_DEFAULT, /* tp_flags */
Benjamin Petersonc4607ae2011-07-29 18:19:43 -050071 0, /* tp_doc */
72 0, /* tp_traverse */
73 0, /* tp_clear */
74 0, /* tp_richcompare */
75 0, /* tp_weaklistoffset */
76 0, /* tp_iter */
77 0, /* tp_iternext */
Alexandre Vassalottic49477b2013-11-24 02:53:45 -080078 ellipsis_methods, /* tp_methods */
Benjamin Petersonc4607ae2011-07-29 18:19:43 -050079 0, /* tp_members */
80 0, /* tp_getset */
81 0, /* tp_base */
82 0, /* tp_dict */
83 0, /* tp_descr_get */
84 0, /* tp_descr_set */
85 0, /* tp_dictoffset */
86 0, /* tp_init */
87 0, /* tp_alloc */
88 ellipsis_new, /* tp_new */
Guido van Rossumf2d125b1996-07-30 16:45:48 +000089};
90
Guido van Rossume449af71996-10-11 16:25:41 +000091PyObject _Py_EllipsisObject = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000092 _PyObject_EXTRA_INIT
93 1, &PyEllipsis_Type
Guido van Rossumf2d125b1996-07-30 16:45:48 +000094};
95
96
Antoine Pitrouf34a0cd2011-11-18 20:14:34 +010097/* Slice object implementation */
Guido van Rossumf2d125b1996-07-30 16:45:48 +000098
Victor Stinnerbed48172019-08-27 00:12:32 +020099
Victor Stinner7daba6f2020-06-05 01:14:40 +0200100void _PySlice_Fini(PyThreadState *tstate)
Antoine Pitrouf34a0cd2011-11-18 20:14:34 +0100101{
Victor Stinner7daba6f2020-06-05 01:14:40 +0200102 PyInterpreterState *interp = tstate->interp;
103 PySliceObject *obj = interp->slice_cache;
Antoine Pitrouf34a0cd2011-11-18 20:14:34 +0100104 if (obj != NULL) {
Victor Stinner7daba6f2020-06-05 01:14:40 +0200105 interp->slice_cache = NULL;
Benjamin Petersonb0c04cb2016-04-16 15:12:29 -0700106 PyObject_GC_Del(obj);
Antoine Pitrouf34a0cd2011-11-18 20:14:34 +0100107 }
108}
109
110/* start, stop, and step are python objects with None indicating no
Guido van Rossumf2d125b1996-07-30 16:45:48 +0000111 index is present.
112*/
113
114PyObject *
Fred Drake45cfbcc2000-07-09 06:21:27 +0000115PySlice_New(PyObject *start, PyObject *stop, PyObject *step)
Guido van Rossumf2d125b1996-07-30 16:45:48 +0000116{
Victor Stinner522691c2020-06-23 16:40:40 +0200117 if (step == NULL) {
118 step = Py_None;
119 }
120 if (start == NULL) {
121 start = Py_None;
122 }
123 if (stop == NULL) {
124 stop = Py_None;
125 }
126
Victor Stinner7daba6f2020-06-05 01:14:40 +0200127 PyInterpreterState *interp = _PyInterpreterState_GET();
Antoine Pitrouf34a0cd2011-11-18 20:14:34 +0100128 PySliceObject *obj;
Victor Stinner7daba6f2020-06-05 01:14:40 +0200129 if (interp->slice_cache != NULL) {
130 obj = interp->slice_cache;
131 interp->slice_cache = NULL;
Antoine Pitrouf34a0cd2011-11-18 20:14:34 +0100132 _Py_NewReference((PyObject *)obj);
Victor Stinner522691c2020-06-23 16:40:40 +0200133 }
134 else {
Benjamin Peterson2b601d32016-04-16 14:47:12 -0700135 obj = PyObject_GC_New(PySliceObject, &PySlice_Type);
Victor Stinner522691c2020-06-23 16:40:40 +0200136 if (obj == NULL) {
Antoine Pitrouf34a0cd2011-11-18 20:14:34 +0100137 return NULL;
Victor Stinner522691c2020-06-23 16:40:40 +0200138 }
Antoine Pitrouf34a0cd2011-11-18 20:14:34 +0100139 }
Guido van Rossumadf54102000-12-14 15:09:46 +0000140
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000141 Py_INCREF(step);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000142 obj->step = step;
Victor Stinner522691c2020-06-23 16:40:40 +0200143 Py_INCREF(start);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000144 obj->start = start;
Victor Stinner522691c2020-06-23 16:40:40 +0200145 Py_INCREF(stop);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000146 obj->stop = stop;
Guido van Rossumf2d125b1996-07-30 16:45:48 +0000147
Benjamin Peterson2b601d32016-04-16 14:47:12 -0700148 _PyObject_GC_TRACK(obj);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000149 return (PyObject *) obj;
Guido van Rossumf2d125b1996-07-30 16:45:48 +0000150}
151
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000152PyObject *
153_PySlice_FromIndices(Py_ssize_t istart, Py_ssize_t istop)
154{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000155 PyObject *start, *end, *slice;
156 start = PyLong_FromSsize_t(istart);
157 if (!start)
158 return NULL;
159 end = PyLong_FromSsize_t(istop);
160 if (!end) {
161 Py_DECREF(start);
162 return NULL;
163 }
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000164
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000165 slice = PySlice_New(start, end, NULL);
166 Py_DECREF(start);
167 Py_DECREF(end);
168 return slice;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000169}
170
Guido van Rossumf2d125b1996-07-30 16:45:48 +0000171int
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000172PySlice_GetIndices(PyObject *_r, Py_ssize_t length,
Martin v. Löwis18e16552006-02-15 17:27:45 +0000173 Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step)
Guido van Rossumf2d125b1996-07-30 16:45:48 +0000174{
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000175 PySliceObject *r = (PySliceObject*)_r;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000176 /* XXX support long ints */
177 if (r->step == Py_None) {
178 *step = 1;
179 } else {
180 if (!PyLong_Check(r->step)) return -1;
181 *step = PyLong_AsSsize_t(r->step);
182 }
183 if (r->start == Py_None) {
184 *start = *step < 0 ? length-1 : 0;
185 } else {
186 if (!PyLong_Check(r->start)) return -1;
187 *start = PyLong_AsSsize_t(r->start);
188 if (*start < 0) *start += length;
189 }
190 if (r->stop == Py_None) {
191 *stop = *step < 0 ? -1 : length;
192 } else {
193 if (!PyLong_Check(r->stop)) return -1;
194 *stop = PyLong_AsSsize_t(r->stop);
195 if (*stop < 0) *stop += length;
196 }
197 if (*stop > length) return -1;
198 if (*start >= length) return -1;
199 if (*step == 0) return -1;
200 return 0;
Guido van Rossumf2d125b1996-07-30 16:45:48 +0000201}
202
Michael W. Hudson5efaf7e2002-06-11 10:55:12 +0000203int
Serhiy Storchakab2a5be02017-01-25 13:23:05 +0200204PySlice_Unpack(PyObject *_r,
205 Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step)
Michael W. Hudson5efaf7e2002-06-11 10:55:12 +0000206{
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000207 PySliceObject *r = (PySliceObject*)_r;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000208 /* this is harder to get right than you might think */
Michael W. Hudson173f11d2002-11-05 15:28:51 +0000209
Xiang Zhang2ddf5a12017-05-10 18:19:41 +0800210 Py_BUILD_ASSERT(PY_SSIZE_T_MIN + 1 <= -PY_SSIZE_T_MAX);
211
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000212 if (r->step == Py_None) {
213 *step = 1;
214 }
215 else {
216 if (!_PyEval_SliceIndex(r->step, step)) return -1;
217 if (*step == 0) {
218 PyErr_SetString(PyExc_ValueError,
219 "slice step cannot be zero");
220 return -1;
221 }
Mark Dickinsone6fc7402010-08-06 18:55:26 +0000222 /* Here *step might be -PY_SSIZE_T_MAX-1; in this case we replace it
223 * with -PY_SSIZE_T_MAX. This doesn't affect the semantics, and it
224 * guards against later undefined behaviour resulting from code that
225 * does "step = -step" as part of a slice reversal.
226 */
227 if (*step < -PY_SSIZE_T_MAX)
228 *step = -PY_SSIZE_T_MAX;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000229 }
Michael W. Hudson5efaf7e2002-06-11 10:55:12 +0000230
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000231 if (r->start == Py_None) {
Xiang Zhang2ddf5a12017-05-10 18:19:41 +0800232 *start = *step < 0 ? PY_SSIZE_T_MAX : 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000233 }
234 else {
235 if (!_PyEval_SliceIndex(r->start, start)) return -1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000236 }
Michael W. Hudson5efaf7e2002-06-11 10:55:12 +0000237
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000238 if (r->stop == Py_None) {
Xiang Zhang2ddf5a12017-05-10 18:19:41 +0800239 *stop = *step < 0 ? PY_SSIZE_T_MIN : PY_SSIZE_T_MAX;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000240 }
241 else {
242 if (!_PyEval_SliceIndex(r->stop, stop)) return -1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000243 }
Michael W. Hudson173f11d2002-11-05 15:28:51 +0000244
Serhiy Storchakab2a5be02017-01-25 13:23:05 +0200245 return 0;
246}
247
248Py_ssize_t
249PySlice_AdjustIndices(Py_ssize_t length,
250 Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t step)
251{
252 /* this is harder to get right than you might think */
253
254 assert(step != 0);
255 assert(step >= -PY_SSIZE_T_MAX);
256
257 if (*start < 0) {
258 *start += length;
259 if (*start < 0) {
260 *start = (step < 0) ? -1 : 0;
261 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000262 }
Serhiy Storchakab2a5be02017-01-25 13:23:05 +0200263 else if (*start >= length) {
264 *start = (step < 0) ? length - 1 : length;
265 }
266
267 if (*stop < 0) {
268 *stop += length;
269 if (*stop < 0) {
270 *stop = (step < 0) ? -1 : 0;
271 }
272 }
Xiang Zhang2ddf5a12017-05-10 18:19:41 +0800273 else if (*stop >= length) {
Serhiy Storchakab2a5be02017-01-25 13:23:05 +0200274 *stop = (step < 0) ? length - 1 : length;
275 }
276
277 if (step < 0) {
278 if (*stop < *start) {
279 return (*start - *stop - 1) / (-step) + 1;
280 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000281 }
282 else {
Serhiy Storchakab2a5be02017-01-25 13:23:05 +0200283 if (*start < *stop) {
284 return (*stop - *start - 1) / step + 1;
285 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000286 }
Serhiy Storchakab2a5be02017-01-25 13:23:05 +0200287 return 0;
288}
Michael W. Hudson5efaf7e2002-06-11 10:55:12 +0000289
Serhiy Storchakab2a5be02017-01-25 13:23:05 +0200290#undef PySlice_GetIndicesEx
291
292int
293PySlice_GetIndicesEx(PyObject *_r, Py_ssize_t length,
294 Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step,
295 Py_ssize_t *slicelength)
296{
297 if (PySlice_Unpack(_r, start, stop, step) < 0)
298 return -1;
299 *slicelength = PySlice_AdjustIndices(length, start, stop, *step);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000300 return 0;
Michael W. Hudson5efaf7e2002-06-11 10:55:12 +0000301}
302
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000303static PyObject *
304slice_new(PyTypeObject *type, PyObject *args, PyObject *kw)
305{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000306 PyObject *start, *stop, *step;
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000307
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000308 start = stop = step = NULL;
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000309
Serhiy Storchaka6cca5c82017-06-08 14:41:19 +0300310 if (!_PyArg_NoKeywords("slice", kw))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000311 return NULL;
Georg Brandl02c42872005-08-26 06:42:30 +0000312
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000313 if (!PyArg_UnpackTuple(args, "slice", 1, 3, &start, &stop, &step))
314 return NULL;
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000315
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000316 /* This swapping of stop and start is to maintain similarity with
317 range(). */
318 if (stop == NULL) {
319 stop = start;
320 start = NULL;
321 }
322 return PySlice_New(start, stop, step);
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000323}
324
325PyDoc_STRVAR(slice_doc,
Chris Jerdonek83fe2e12012-10-07 14:48:36 -0700326"slice(stop)\n\
327slice(start, stop[, step])\n\
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000328\n\
329Create a slice object. This is used for extended slicing (e.g. a[0:10:2]).");
330
Guido van Rossumf2d125b1996-07-30 16:45:48 +0000331static void
Fred Drake45cfbcc2000-07-09 06:21:27 +0000332slice_dealloc(PySliceObject *r)
Guido van Rossumf2d125b1996-07-30 16:45:48 +0000333{
Victor Stinner7daba6f2020-06-05 01:14:40 +0200334 PyInterpreterState *interp = _PyInterpreterState_GET();
Benjamin Peterson2b601d32016-04-16 14:47:12 -0700335 _PyObject_GC_UNTRACK(r);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000336 Py_DECREF(r->step);
337 Py_DECREF(r->start);
338 Py_DECREF(r->stop);
Victor Stinner7daba6f2020-06-05 01:14:40 +0200339 if (interp->slice_cache == NULL) {
340 interp->slice_cache = r;
341 }
342 else {
Benjamin Peterson2b601d32016-04-16 14:47:12 -0700343 PyObject_GC_Del(r);
Victor Stinner7daba6f2020-06-05 01:14:40 +0200344 }
Guido van Rossumf2d125b1996-07-30 16:45:48 +0000345}
346
347static PyObject *
Fred Drake45cfbcc2000-07-09 06:21:27 +0000348slice_repr(PySliceObject *r)
Guido van Rossumf2d125b1996-07-30 16:45:48 +0000349{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000350 return PyUnicode_FromFormat("slice(%R, %R, %R)", r->start, r->stop, r->step);
Guido van Rossumf2d125b1996-07-30 16:45:48 +0000351}
352
Guido van Rossum6f799372001-09-20 20:46:19 +0000353static PyMemberDef slice_members[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000354 {"start", T_OBJECT, offsetof(PySliceObject, start), READONLY},
355 {"stop", T_OBJECT, offsetof(PySliceObject, stop), READONLY},
356 {"step", T_OBJECT, offsetof(PySliceObject, step), READONLY},
357 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +0000358};
Guido van Rossumf2d125b1996-07-30 16:45:48 +0000359
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000360/* Helper function to convert a slice argument to a PyLong, and raise TypeError
361 with a suitable message on failure. */
362
363static PyObject*
364evaluate_slice_index(PyObject *v)
365{
Victor Stinnera15e2602020-04-08 02:01:56 +0200366 if (_PyIndex_Check(v)) {
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000367 return PyNumber_Index(v);
368 }
369 else {
370 PyErr_SetString(PyExc_TypeError,
371 "slice indices must be integers or "
372 "None or have an __index__ method");
373 return NULL;
374 }
375}
376
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000377/* Compute slice indices given a slice and length. Return -1 on failure. Used
378 by slice.indices and rangeobject slicing. Assumes that `len` is a
379 nonnegative instance of PyLong. */
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000380
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000381int
382_PySlice_GetLongIndices(PySliceObject *self, PyObject *length,
383 PyObject **start_ptr, PyObject **stop_ptr,
384 PyObject **step_ptr)
Michael W. Hudsonf0d777c2002-07-19 15:47:06 +0000385{
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000386 PyObject *start=NULL, *stop=NULL, *step=NULL;
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000387 PyObject *upper=NULL, *lower=NULL;
388 int step_is_negative, cmp_result;
Michael W. Hudsonf0d777c2002-07-19 15:47:06 +0000389
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000390 /* Convert step to an integer; raise for zero step. */
391 if (self->step == Py_None) {
Victor Stinnerc9bc2902020-10-27 02:24:34 +0100392 step = _PyLong_GetOne();
Serhiy Storchakaba85d692017-03-30 09:09:41 +0300393 Py_INCREF(step);
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000394 step_is_negative = 0;
395 }
396 else {
397 int step_sign;
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000398 step = evaluate_slice_index(self->step);
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000399 if (step == NULL)
400 goto error;
401 step_sign = _PyLong_Sign(step);
402 if (step_sign == 0) {
403 PyErr_SetString(PyExc_ValueError,
404 "slice step cannot be zero");
405 goto error;
406 }
407 step_is_negative = step_sign < 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000408 }
Michael W. Hudsonf0d777c2002-07-19 15:47:06 +0000409
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000410 /* Find lower and upper bounds for start and stop. */
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000411 if (step_is_negative) {
412 lower = PyLong_FromLong(-1L);
413 if (lower == NULL)
414 goto error;
415
416 upper = PyNumber_Add(length, lower);
417 if (upper == NULL)
418 goto error;
419 }
420 else {
Victor Stinnerc9bc2902020-10-27 02:24:34 +0100421 lower = _PyLong_GetZero();
Serhiy Storchakaba85d692017-03-30 09:09:41 +0300422 Py_INCREF(lower);
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000423 upper = length;
424 Py_INCREF(upper);
425 }
426
427 /* Compute start. */
428 if (self->start == Py_None) {
429 start = step_is_negative ? upper : lower;
430 Py_INCREF(start);
431 }
432 else {
433 start = evaluate_slice_index(self->start);
434 if (start == NULL)
435 goto error;
436
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000437 if (_PyLong_Sign(start) < 0) {
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000438 /* start += length */
439 PyObject *tmp = PyNumber_Add(start, length);
440 Py_DECREF(start);
441 start = tmp;
442 if (start == NULL)
443 goto error;
444
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000445 cmp_result = PyObject_RichCompareBool(start, lower, Py_LT);
446 if (cmp_result < 0)
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000447 goto error;
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000448 if (cmp_result) {
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000449 Py_INCREF(lower);
450 Py_DECREF(start);
451 start = lower;
452 }
453 }
454 else {
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000455 cmp_result = PyObject_RichCompareBool(start, upper, Py_GT);
456 if (cmp_result < 0)
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000457 goto error;
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000458 if (cmp_result) {
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000459 Py_INCREF(upper);
460 Py_DECREF(start);
461 start = upper;
462 }
463 }
464 }
465
466 /* Compute stop. */
467 if (self->stop == Py_None) {
468 stop = step_is_negative ? lower : upper;
469 Py_INCREF(stop);
470 }
471 else {
472 stop = evaluate_slice_index(self->stop);
473 if (stop == NULL)
474 goto error;
475
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000476 if (_PyLong_Sign(stop) < 0) {
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000477 /* stop += length */
478 PyObject *tmp = PyNumber_Add(stop, length);
479 Py_DECREF(stop);
480 stop = tmp;
481 if (stop == NULL)
482 goto error;
483
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000484 cmp_result = PyObject_RichCompareBool(stop, lower, Py_LT);
485 if (cmp_result < 0)
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000486 goto error;
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000487 if (cmp_result) {
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000488 Py_INCREF(lower);
489 Py_DECREF(stop);
490 stop = lower;
491 }
492 }
493 else {
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000494 cmp_result = PyObject_RichCompareBool(stop, upper, Py_GT);
495 if (cmp_result < 0)
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000496 goto error;
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000497 if (cmp_result) {
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000498 Py_INCREF(upper);
499 Py_DECREF(stop);
500 stop = upper;
501 }
502 }
503 }
504
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000505 *start_ptr = start;
506 *stop_ptr = stop;
507 *step_ptr = step;
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000508 Py_DECREF(upper);
509 Py_DECREF(lower);
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000510 return 0;
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000511
512 error:
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000513 *start_ptr = *stop_ptr = *step_ptr = NULL;
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000514 Py_XDECREF(start);
515 Py_XDECREF(stop);
516 Py_XDECREF(step);
517 Py_XDECREF(upper);
518 Py_XDECREF(lower);
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000519 return -1;
Michael W. Hudsonf0d777c2002-07-19 15:47:06 +0000520}
521
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000522/* Implementation of slice.indices. */
523
524static PyObject*
525slice_indices(PySliceObject* self, PyObject* len)
526{
527 PyObject *start, *stop, *step;
528 PyObject *length;
529 int error;
530
531 /* Convert length to an integer if necessary; raise for negative length. */
532 length = PyNumber_Index(len);
533 if (length == NULL)
534 return NULL;
535
536 if (_PyLong_Sign(length) < 0) {
537 PyErr_SetString(PyExc_ValueError,
538 "length should not be negative");
539 Py_DECREF(length);
540 return NULL;
541 }
542
543 error = _PySlice_GetLongIndices(self, length, &start, &stop, &step);
544 Py_DECREF(length);
545 if (error == -1)
546 return NULL;
547 else
548 return Py_BuildValue("(NNN)", start, stop, step);
549}
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000550
Michael W. Hudsonf0d777c2002-07-19 15:47:06 +0000551PyDoc_STRVAR(slice_indices_doc,
552"S.indices(len) -> (start, stop, stride)\n\
553\n\
554Assuming a sequence of length len, calculate the start and stop\n\
555indices, and the stride length of the extended slice described by\n\
556S. Out of bounds indices are clipped in a manner consistent with the\n\
557handling of normal slices.");
558
Guido van Rossumd8faa362007-04-27 19:54:29 +0000559static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530560slice_reduce(PySliceObject* self, PyObject *Py_UNUSED(ignored))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000561{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000562 return Py_BuildValue("O(OOO)", Py_TYPE(self), self->start, self->stop, self->step);
Guido van Rossumd8faa362007-04-27 19:54:29 +0000563}
564
565PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
566
Michael W. Hudsonf0d777c2002-07-19 15:47:06 +0000567static PyMethodDef slice_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000568 {"indices", (PyCFunction)slice_indices,
569 METH_O, slice_indices_doc},
570 {"__reduce__", (PyCFunction)slice_reduce,
571 METH_NOARGS, reduce_doc},
572 {NULL, NULL}
Michael W. Hudsonf0d777c2002-07-19 15:47:06 +0000573};
574
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000575static PyObject *
576slice_richcompare(PyObject *v, PyObject *w, int op)
Guido van Rossuma1351fb2001-03-20 12:41:34 +0000577{
Brian Curtindfc80e32011-08-10 20:28:54 -0500578 if (!PySlice_Check(v) || !PySlice_Check(w))
579 Py_RETURN_NOTIMPLEMENTED;
Thomas Wouters3e57b522007-08-28 23:07:26 +0000580
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000581 if (v == w) {
Victor Stinnerdcb68f42019-02-13 12:31:56 +0100582 PyObject *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000583 /* XXX Do we really need this shortcut?
584 There's a unit test for it, but is that fair? */
585 switch (op) {
586 case Py_EQ:
587 case Py_LE:
588 case Py_GE:
589 res = Py_True;
590 break;
591 default:
592 res = Py_False;
593 break;
594 }
595 Py_INCREF(res);
596 return res;
597 }
Guido van Rossuma1351fb2001-03-20 12:41:34 +0000598
Victor Stinnerdcb68f42019-02-13 12:31:56 +0100599
600 PyObject *t1 = PyTuple_Pack(3,
601 ((PySliceObject *)v)->start,
602 ((PySliceObject *)v)->stop,
603 ((PySliceObject *)v)->step);
604 if (t1 == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000605 return NULL;
Victor Stinnerdcb68f42019-02-13 12:31:56 +0100606 }
607
608 PyObject *t2 = PyTuple_Pack(3,
609 ((PySliceObject *)w)->start,
610 ((PySliceObject *)w)->stop,
611 ((PySliceObject *)w)->step);
Benjamin Peterson2963fe02011-10-17 13:09:27 -0400612 if (t2 == NULL) {
613 Py_DECREF(t1);
614 return NULL;
615 }
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000616
Victor Stinnerdcb68f42019-02-13 12:31:56 +0100617 PyObject *res = PyObject_RichCompare(t1, t2, op);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000618 Py_DECREF(t1);
619 Py_DECREF(t2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000620 return res;
Guido van Rossuma1351fb2001-03-20 12:41:34 +0000621}
Guido van Rossumf2d125b1996-07-30 16:45:48 +0000622
Benjamin Peterson2b601d32016-04-16 14:47:12 -0700623static int
624slice_traverse(PySliceObject *v, visitproc visit, void *arg)
625{
626 Py_VISIT(v->start);
627 Py_VISIT(v->stop);
628 Py_VISIT(v->step);
629 return 0;
630}
631
Guido van Rossumf2d125b1996-07-30 16:45:48 +0000632PyTypeObject PySlice_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000633 PyVarObject_HEAD_INIT(&PyType_Type, 0)
634 "slice", /* Name of this type */
635 sizeof(PySliceObject), /* Basic object size */
636 0, /* Item size for varobject */
637 (destructor)slice_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200638 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000639 0, /* tp_getattr */
640 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200641 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000642 (reprfunc)slice_repr, /* tp_repr */
643 0, /* tp_as_number */
644 0, /* tp_as_sequence */
645 0, /* tp_as_mapping */
Benjamin Peterson23d05c12010-10-17 20:13:05 +0000646 PyObject_HashNotImplemented, /* tp_hash */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000647 0, /* tp_call */
648 0, /* tp_str */
649 PyObject_GenericGetAttr, /* tp_getattro */
650 0, /* tp_setattro */
651 0, /* tp_as_buffer */
Benjamin Peterson2b601d32016-04-16 14:47:12 -0700652 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000653 slice_doc, /* tp_doc */
Benjamin Peterson2b601d32016-04-16 14:47:12 -0700654 (traverseproc)slice_traverse, /* tp_traverse */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000655 0, /* tp_clear */
656 slice_richcompare, /* tp_richcompare */
657 0, /* tp_weaklistoffset */
658 0, /* tp_iter */
659 0, /* tp_iternext */
660 slice_methods, /* tp_methods */
661 slice_members, /* tp_members */
662 0, /* tp_getset */
663 0, /* tp_base */
664 0, /* tp_dict */
665 0, /* tp_descr_get */
666 0, /* tp_descr_set */
667 0, /* tp_dictoffset */
668 0, /* tp_init */
669 0, /* tp_alloc */
670 slice_new, /* tp_new */
Guido van Rossumf2d125b1996-07-30 16:45:48 +0000671};