blob: 59f084d1a612cc36c2fa4e63a913a9d9b1f89a96 [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"
Eric Snow2ebc5ce2017-09-07 23:51:28 -060017#include "internal/mem.h"
18#include "internal/pystate.h"
Tim Peters6d6c1a32001-08-02 04:15:00 +000019#include "structmember.h"
Guido van Rossumf2d125b1996-07-30 16:45:48 +000020
21static PyObject *
Benjamin Petersonc4607ae2011-07-29 18:19:43 -050022ellipsis_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
23{
Serhiy Storchaka5ab81d72016-12-16 16:18:57 +020024 if (PyTuple_GET_SIZE(args) || (kwargs && PyDict_GET_SIZE(kwargs))) {
Benjamin Petersonc4607ae2011-07-29 18:19:43 -050025 PyErr_SetString(PyExc_TypeError, "EllipsisType takes no arguments");
26 return NULL;
27 }
28 Py_INCREF(Py_Ellipsis);
29 return Py_Ellipsis;
30}
31
32static PyObject *
Fred Drake45cfbcc2000-07-09 06:21:27 +000033ellipsis_repr(PyObject *op)
Guido van Rossumf2d125b1996-07-30 16:45:48 +000034{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000035 return PyUnicode_FromString("Ellipsis");
Guido van Rossumf2d125b1996-07-30 16:45:48 +000036}
37
Alexandre Vassalottic49477b2013-11-24 02:53:45 -080038static PyObject *
39ellipsis_reduce(PyObject *op)
40{
41 return PyUnicode_FromString("Ellipsis");
42}
43
44static PyMethodDef ellipsis_methods[] = {
45 {"__reduce__", (PyCFunction)ellipsis_reduce, METH_NOARGS, NULL},
46 {NULL, NULL}
47};
48
Benjamin Petersonfd838e62009-04-20 02:09:13 +000049PyTypeObject PyEllipsis_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000050 PyVarObject_HEAD_INIT(&PyType_Type, 0)
51 "ellipsis", /* tp_name */
52 0, /* tp_basicsize */
53 0, /* tp_itemsize */
54 0, /*never called*/ /* tp_dealloc */
55 0, /* tp_print */
56 0, /* tp_getattr */
57 0, /* tp_setattr */
58 0, /* tp_reserved */
59 ellipsis_repr, /* tp_repr */
60 0, /* tp_as_number */
61 0, /* tp_as_sequence */
62 0, /* tp_as_mapping */
63 0, /* tp_hash */
64 0, /* tp_call */
65 0, /* tp_str */
66 PyObject_GenericGetAttr, /* tp_getattro */
67 0, /* tp_setattro */
68 0, /* tp_as_buffer */
69 Py_TPFLAGS_DEFAULT, /* tp_flags */
Benjamin Petersonc4607ae2011-07-29 18:19:43 -050070 0, /* tp_doc */
71 0, /* tp_traverse */
72 0, /* tp_clear */
73 0, /* tp_richcompare */
74 0, /* tp_weaklistoffset */
75 0, /* tp_iter */
76 0, /* tp_iternext */
Alexandre Vassalottic49477b2013-11-24 02:53:45 -080077 ellipsis_methods, /* tp_methods */
Benjamin Petersonc4607ae2011-07-29 18:19:43 -050078 0, /* tp_members */
79 0, /* tp_getset */
80 0, /* tp_base */
81 0, /* tp_dict */
82 0, /* tp_descr_get */
83 0, /* tp_descr_set */
84 0, /* tp_dictoffset */
85 0, /* tp_init */
86 0, /* tp_alloc */
87 ellipsis_new, /* tp_new */
Guido van Rossumf2d125b1996-07-30 16:45:48 +000088};
89
Guido van Rossume449af71996-10-11 16:25:41 +000090PyObject _Py_EllipsisObject = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000091 _PyObject_EXTRA_INIT
92 1, &PyEllipsis_Type
Guido van Rossumf2d125b1996-07-30 16:45:48 +000093};
94
95
Antoine Pitrouf34a0cd2011-11-18 20:14:34 +010096/* Slice object implementation */
Guido van Rossumf2d125b1996-07-30 16:45:48 +000097
Antoine Pitrouf34a0cd2011-11-18 20:14:34 +010098/* Using a cache is very effective since typically only a single slice is
99 * created and then deleted again
100 */
101static PySliceObject *slice_cache = NULL;
102void PySlice_Fini(void)
103{
104 PySliceObject *obj = slice_cache;
105 if (obj != NULL) {
106 slice_cache = NULL;
Benjamin Petersonb0c04cb2016-04-16 15:12:29 -0700107 PyObject_GC_Del(obj);
Antoine Pitrouf34a0cd2011-11-18 20:14:34 +0100108 }
109}
110
111/* start, stop, and step are python objects with None indicating no
Guido van Rossumf2d125b1996-07-30 16:45:48 +0000112 index is present.
113*/
114
115PyObject *
Fred Drake45cfbcc2000-07-09 06:21:27 +0000116PySlice_New(PyObject *start, PyObject *stop, PyObject *step)
Guido van Rossumf2d125b1996-07-30 16:45:48 +0000117{
Antoine Pitrouf34a0cd2011-11-18 20:14:34 +0100118 PySliceObject *obj;
119 if (slice_cache != NULL) {
120 obj = slice_cache;
121 slice_cache = NULL;
122 _Py_NewReference((PyObject *)obj);
123 } else {
Benjamin Peterson2b601d32016-04-16 14:47:12 -0700124 obj = PyObject_GC_New(PySliceObject, &PySlice_Type);
Antoine Pitrouf34a0cd2011-11-18 20:14:34 +0100125 if (obj == NULL)
126 return NULL;
127 }
Guido van Rossumadf54102000-12-14 15:09:46 +0000128
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000129 if (step == NULL) step = Py_None;
130 Py_INCREF(step);
131 if (start == NULL) start = Py_None;
132 Py_INCREF(start);
133 if (stop == NULL) stop = Py_None;
134 Py_INCREF(stop);
Guido van Rossumf2d125b1996-07-30 16:45:48 +0000135
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000136 obj->step = step;
137 obj->start = start;
138 obj->stop = stop;
Guido van Rossumf2d125b1996-07-30 16:45:48 +0000139
Benjamin Peterson2b601d32016-04-16 14:47:12 -0700140 _PyObject_GC_TRACK(obj);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000141 return (PyObject *) obj;
Guido van Rossumf2d125b1996-07-30 16:45:48 +0000142}
143
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000144PyObject *
145_PySlice_FromIndices(Py_ssize_t istart, Py_ssize_t istop)
146{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000147 PyObject *start, *end, *slice;
148 start = PyLong_FromSsize_t(istart);
149 if (!start)
150 return NULL;
151 end = PyLong_FromSsize_t(istop);
152 if (!end) {
153 Py_DECREF(start);
154 return NULL;
155 }
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000156
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000157 slice = PySlice_New(start, end, NULL);
158 Py_DECREF(start);
159 Py_DECREF(end);
160 return slice;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000161}
162
Guido van Rossumf2d125b1996-07-30 16:45:48 +0000163int
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000164PySlice_GetIndices(PyObject *_r, Py_ssize_t length,
Martin v. Löwis18e16552006-02-15 17:27:45 +0000165 Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step)
Guido van Rossumf2d125b1996-07-30 16:45:48 +0000166{
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000167 PySliceObject *r = (PySliceObject*)_r;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000168 /* XXX support long ints */
169 if (r->step == Py_None) {
170 *step = 1;
171 } else {
172 if (!PyLong_Check(r->step)) return -1;
173 *step = PyLong_AsSsize_t(r->step);
174 }
175 if (r->start == Py_None) {
176 *start = *step < 0 ? length-1 : 0;
177 } else {
178 if (!PyLong_Check(r->start)) return -1;
179 *start = PyLong_AsSsize_t(r->start);
180 if (*start < 0) *start += length;
181 }
182 if (r->stop == Py_None) {
183 *stop = *step < 0 ? -1 : length;
184 } else {
185 if (!PyLong_Check(r->stop)) return -1;
186 *stop = PyLong_AsSsize_t(r->stop);
187 if (*stop < 0) *stop += length;
188 }
189 if (*stop > length) return -1;
190 if (*start >= length) return -1;
191 if (*step == 0) return -1;
192 return 0;
Guido van Rossumf2d125b1996-07-30 16:45:48 +0000193}
194
Michael W. Hudson5efaf7e2002-06-11 10:55:12 +0000195int
Serhiy Storchakab2a5be02017-01-25 13:23:05 +0200196PySlice_Unpack(PyObject *_r,
197 Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step)
Michael W. Hudson5efaf7e2002-06-11 10:55:12 +0000198{
Martin v. Löwis4d0d4712010-12-03 20:14:31 +0000199 PySliceObject *r = (PySliceObject*)_r;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000200 /* this is harder to get right than you might think */
Michael W. Hudson173f11d2002-11-05 15:28:51 +0000201
Xiang Zhang2ddf5a12017-05-10 18:19:41 +0800202 Py_BUILD_ASSERT(PY_SSIZE_T_MIN + 1 <= -PY_SSIZE_T_MAX);
203
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000204 if (r->step == Py_None) {
205 *step = 1;
206 }
207 else {
208 if (!_PyEval_SliceIndex(r->step, step)) return -1;
209 if (*step == 0) {
210 PyErr_SetString(PyExc_ValueError,
211 "slice step cannot be zero");
212 return -1;
213 }
Mark Dickinsone6fc7402010-08-06 18:55:26 +0000214 /* Here *step might be -PY_SSIZE_T_MAX-1; in this case we replace it
215 * with -PY_SSIZE_T_MAX. This doesn't affect the semantics, and it
216 * guards against later undefined behaviour resulting from code that
217 * does "step = -step" as part of a slice reversal.
218 */
219 if (*step < -PY_SSIZE_T_MAX)
220 *step = -PY_SSIZE_T_MAX;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000221 }
Michael W. Hudson5efaf7e2002-06-11 10:55:12 +0000222
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000223 if (r->start == Py_None) {
Xiang Zhang2ddf5a12017-05-10 18:19:41 +0800224 *start = *step < 0 ? PY_SSIZE_T_MAX : 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000225 }
226 else {
227 if (!_PyEval_SliceIndex(r->start, start)) return -1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000228 }
Michael W. Hudson5efaf7e2002-06-11 10:55:12 +0000229
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000230 if (r->stop == Py_None) {
Xiang Zhang2ddf5a12017-05-10 18:19:41 +0800231 *stop = *step < 0 ? PY_SSIZE_T_MIN : PY_SSIZE_T_MAX;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000232 }
233 else {
234 if (!_PyEval_SliceIndex(r->stop, stop)) return -1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000235 }
Michael W. Hudson173f11d2002-11-05 15:28:51 +0000236
Serhiy Storchakab2a5be02017-01-25 13:23:05 +0200237 return 0;
238}
239
240Py_ssize_t
241PySlice_AdjustIndices(Py_ssize_t length,
242 Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t step)
243{
244 /* this is harder to get right than you might think */
245
246 assert(step != 0);
247 assert(step >= -PY_SSIZE_T_MAX);
248
249 if (*start < 0) {
250 *start += length;
251 if (*start < 0) {
252 *start = (step < 0) ? -1 : 0;
253 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000254 }
Serhiy Storchakab2a5be02017-01-25 13:23:05 +0200255 else if (*start >= length) {
256 *start = (step < 0) ? length - 1 : length;
257 }
258
259 if (*stop < 0) {
260 *stop += length;
261 if (*stop < 0) {
262 *stop = (step < 0) ? -1 : 0;
263 }
264 }
Xiang Zhang2ddf5a12017-05-10 18:19:41 +0800265 else if (*stop >= length) {
Serhiy Storchakab2a5be02017-01-25 13:23:05 +0200266 *stop = (step < 0) ? length - 1 : length;
267 }
268
269 if (step < 0) {
270 if (*stop < *start) {
271 return (*start - *stop - 1) / (-step) + 1;
272 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000273 }
274 else {
Serhiy Storchakab2a5be02017-01-25 13:23:05 +0200275 if (*start < *stop) {
276 return (*stop - *start - 1) / step + 1;
277 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000278 }
Serhiy Storchakab2a5be02017-01-25 13:23:05 +0200279 return 0;
280}
Michael W. Hudson5efaf7e2002-06-11 10:55:12 +0000281
Serhiy Storchakab2a5be02017-01-25 13:23:05 +0200282#undef PySlice_GetIndicesEx
283
284int
285PySlice_GetIndicesEx(PyObject *_r, Py_ssize_t length,
286 Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step,
287 Py_ssize_t *slicelength)
288{
289 if (PySlice_Unpack(_r, start, stop, step) < 0)
290 return -1;
291 *slicelength = PySlice_AdjustIndices(length, start, stop, *step);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000292 return 0;
Michael W. Hudson5efaf7e2002-06-11 10:55:12 +0000293}
294
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000295static PyObject *
296slice_new(PyTypeObject *type, PyObject *args, PyObject *kw)
297{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000298 PyObject *start, *stop, *step;
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000299
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000300 start = stop = step = NULL;
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000301
Serhiy Storchaka6cca5c82017-06-08 14:41:19 +0300302 if (!_PyArg_NoKeywords("slice", kw))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000303 return NULL;
Georg Brandl02c42872005-08-26 06:42:30 +0000304
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000305 if (!PyArg_UnpackTuple(args, "slice", 1, 3, &start, &stop, &step))
306 return NULL;
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000307
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000308 /* This swapping of stop and start is to maintain similarity with
309 range(). */
310 if (stop == NULL) {
311 stop = start;
312 start = NULL;
313 }
314 return PySlice_New(start, stop, step);
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000315}
316
317PyDoc_STRVAR(slice_doc,
Chris Jerdonek83fe2e12012-10-07 14:48:36 -0700318"slice(stop)\n\
319slice(start, stop[, step])\n\
Guido van Rossumbea18cc2002-06-14 20:41:17 +0000320\n\
321Create a slice object. This is used for extended slicing (e.g. a[0:10:2]).");
322
Guido van Rossumf2d125b1996-07-30 16:45:48 +0000323static void
Fred Drake45cfbcc2000-07-09 06:21:27 +0000324slice_dealloc(PySliceObject *r)
Guido van Rossumf2d125b1996-07-30 16:45:48 +0000325{
Benjamin Peterson2b601d32016-04-16 14:47:12 -0700326 _PyObject_GC_UNTRACK(r);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000327 Py_DECREF(r->step);
328 Py_DECREF(r->start);
329 Py_DECREF(r->stop);
Antoine Pitrouf34a0cd2011-11-18 20:14:34 +0100330 if (slice_cache == NULL)
331 slice_cache = r;
332 else
Benjamin Peterson2b601d32016-04-16 14:47:12 -0700333 PyObject_GC_Del(r);
Guido van Rossumf2d125b1996-07-30 16:45:48 +0000334}
335
336static PyObject *
Fred Drake45cfbcc2000-07-09 06:21:27 +0000337slice_repr(PySliceObject *r)
Guido van Rossumf2d125b1996-07-30 16:45:48 +0000338{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000339 return PyUnicode_FromFormat("slice(%R, %R, %R)", r->start, r->stop, r->step);
Guido van Rossumf2d125b1996-07-30 16:45:48 +0000340}
341
Guido van Rossum6f799372001-09-20 20:46:19 +0000342static PyMemberDef slice_members[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000343 {"start", T_OBJECT, offsetof(PySliceObject, start), READONLY},
344 {"stop", T_OBJECT, offsetof(PySliceObject, stop), READONLY},
345 {"step", T_OBJECT, offsetof(PySliceObject, step), READONLY},
346 {0}
Tim Peters6d6c1a32001-08-02 04:15:00 +0000347};
Guido van Rossumf2d125b1996-07-30 16:45:48 +0000348
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000349/* Helper function to convert a slice argument to a PyLong, and raise TypeError
350 with a suitable message on failure. */
351
352static PyObject*
353evaluate_slice_index(PyObject *v)
354{
355 if (PyIndex_Check(v)) {
356 return PyNumber_Index(v);
357 }
358 else {
359 PyErr_SetString(PyExc_TypeError,
360 "slice indices must be integers or "
361 "None or have an __index__ method");
362 return NULL;
363 }
364}
365
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000366/* Compute slice indices given a slice and length. Return -1 on failure. Used
367 by slice.indices and rangeobject slicing. Assumes that `len` is a
368 nonnegative instance of PyLong. */
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000369
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000370int
371_PySlice_GetLongIndices(PySliceObject *self, PyObject *length,
372 PyObject **start_ptr, PyObject **stop_ptr,
373 PyObject **step_ptr)
Michael W. Hudsonf0d777c2002-07-19 15:47:06 +0000374{
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000375 PyObject *start=NULL, *stop=NULL, *step=NULL;
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000376 PyObject *upper=NULL, *lower=NULL;
377 int step_is_negative, cmp_result;
Michael W. Hudsonf0d777c2002-07-19 15:47:06 +0000378
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000379 /* Convert step to an integer; raise for zero step. */
380 if (self->step == Py_None) {
Serhiy Storchakaba85d692017-03-30 09:09:41 +0300381 step = _PyLong_One;
382 Py_INCREF(step);
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000383 step_is_negative = 0;
384 }
385 else {
386 int step_sign;
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000387 step = evaluate_slice_index(self->step);
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000388 if (step == NULL)
389 goto error;
390 step_sign = _PyLong_Sign(step);
391 if (step_sign == 0) {
392 PyErr_SetString(PyExc_ValueError,
393 "slice step cannot be zero");
394 goto error;
395 }
396 step_is_negative = step_sign < 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000397 }
Michael W. Hudsonf0d777c2002-07-19 15:47:06 +0000398
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000399 /* Find lower and upper bounds for start and stop. */
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000400 if (step_is_negative) {
401 lower = PyLong_FromLong(-1L);
402 if (lower == NULL)
403 goto error;
404
405 upper = PyNumber_Add(length, lower);
406 if (upper == NULL)
407 goto error;
408 }
409 else {
Serhiy Storchakaba85d692017-03-30 09:09:41 +0300410 lower = _PyLong_Zero;
411 Py_INCREF(lower);
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000412 upper = length;
413 Py_INCREF(upper);
414 }
415
416 /* Compute start. */
417 if (self->start == Py_None) {
418 start = step_is_negative ? upper : lower;
419 Py_INCREF(start);
420 }
421 else {
422 start = evaluate_slice_index(self->start);
423 if (start == NULL)
424 goto error;
425
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000426 if (_PyLong_Sign(start) < 0) {
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000427 /* start += length */
428 PyObject *tmp = PyNumber_Add(start, length);
429 Py_DECREF(start);
430 start = tmp;
431 if (start == NULL)
432 goto error;
433
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000434 cmp_result = PyObject_RichCompareBool(start, lower, Py_LT);
435 if (cmp_result < 0)
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000436 goto error;
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000437 if (cmp_result) {
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000438 Py_INCREF(lower);
439 Py_DECREF(start);
440 start = lower;
441 }
442 }
443 else {
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000444 cmp_result = PyObject_RichCompareBool(start, upper, Py_GT);
445 if (cmp_result < 0)
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000446 goto error;
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000447 if (cmp_result) {
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000448 Py_INCREF(upper);
449 Py_DECREF(start);
450 start = upper;
451 }
452 }
453 }
454
455 /* Compute stop. */
456 if (self->stop == Py_None) {
457 stop = step_is_negative ? lower : upper;
458 Py_INCREF(stop);
459 }
460 else {
461 stop = evaluate_slice_index(self->stop);
462 if (stop == NULL)
463 goto error;
464
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000465 if (_PyLong_Sign(stop) < 0) {
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000466 /* stop += length */
467 PyObject *tmp = PyNumber_Add(stop, length);
468 Py_DECREF(stop);
469 stop = tmp;
470 if (stop == NULL)
471 goto error;
472
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000473 cmp_result = PyObject_RichCompareBool(stop, lower, Py_LT);
474 if (cmp_result < 0)
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000475 goto error;
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000476 if (cmp_result) {
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000477 Py_INCREF(lower);
478 Py_DECREF(stop);
479 stop = lower;
480 }
481 }
482 else {
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000483 cmp_result = PyObject_RichCompareBool(stop, upper, Py_GT);
484 if (cmp_result < 0)
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000485 goto error;
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000486 if (cmp_result) {
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000487 Py_INCREF(upper);
488 Py_DECREF(stop);
489 stop = upper;
490 }
491 }
492 }
493
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000494 *start_ptr = start;
495 *stop_ptr = stop;
496 *step_ptr = step;
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000497 Py_DECREF(upper);
498 Py_DECREF(lower);
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000499 return 0;
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000500
501 error:
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000502 *start_ptr = *stop_ptr = *step_ptr = NULL;
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000503 Py_XDECREF(start);
504 Py_XDECREF(stop);
505 Py_XDECREF(step);
506 Py_XDECREF(upper);
507 Py_XDECREF(lower);
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000508 return -1;
Michael W. Hudsonf0d777c2002-07-19 15:47:06 +0000509}
510
Mark Dickinsonffdb2c22012-11-17 19:18:10 +0000511/* Implementation of slice.indices. */
512
513static PyObject*
514slice_indices(PySliceObject* self, PyObject* len)
515{
516 PyObject *start, *stop, *step;
517 PyObject *length;
518 int error;
519
520 /* Convert length to an integer if necessary; raise for negative length. */
521 length = PyNumber_Index(len);
522 if (length == NULL)
523 return NULL;
524
525 if (_PyLong_Sign(length) < 0) {
526 PyErr_SetString(PyExc_ValueError,
527 "length should not be negative");
528 Py_DECREF(length);
529 return NULL;
530 }
531
532 error = _PySlice_GetLongIndices(self, length, &start, &stop, &step);
533 Py_DECREF(length);
534 if (error == -1)
535 return NULL;
536 else
537 return Py_BuildValue("(NNN)", start, stop, step);
538}
Mark Dickinsonc8a69672012-11-10 14:52:10 +0000539
Michael W. Hudsonf0d777c2002-07-19 15:47:06 +0000540PyDoc_STRVAR(slice_indices_doc,
541"S.indices(len) -> (start, stop, stride)\n\
542\n\
543Assuming a sequence of length len, calculate the start and stop\n\
544indices, and the stride length of the extended slice described by\n\
545S. Out of bounds indices are clipped in a manner consistent with the\n\
546handling of normal slices.");
547
Guido van Rossumd8faa362007-04-27 19:54:29 +0000548static PyObject *
549slice_reduce(PySliceObject* self)
550{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000551 return Py_BuildValue("O(OOO)", Py_TYPE(self), self->start, self->stop, self->step);
Guido van Rossumd8faa362007-04-27 19:54:29 +0000552}
553
554PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
555
Michael W. Hudsonf0d777c2002-07-19 15:47:06 +0000556static PyMethodDef slice_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000557 {"indices", (PyCFunction)slice_indices,
558 METH_O, slice_indices_doc},
559 {"__reduce__", (PyCFunction)slice_reduce,
560 METH_NOARGS, reduce_doc},
561 {NULL, NULL}
Michael W. Hudsonf0d777c2002-07-19 15:47:06 +0000562};
563
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000564static PyObject *
565slice_richcompare(PyObject *v, PyObject *w, int op)
Guido van Rossuma1351fb2001-03-20 12:41:34 +0000566{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000567 PyObject *t1;
568 PyObject *t2;
569 PyObject *res;
Guido van Rossuma1351fb2001-03-20 12:41:34 +0000570
Brian Curtindfc80e32011-08-10 20:28:54 -0500571 if (!PySlice_Check(v) || !PySlice_Check(w))
572 Py_RETURN_NOTIMPLEMENTED;
Thomas Wouters3e57b522007-08-28 23:07:26 +0000573
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000574 if (v == w) {
575 /* XXX Do we really need this shortcut?
576 There's a unit test for it, but is that fair? */
577 switch (op) {
578 case Py_EQ:
579 case Py_LE:
580 case Py_GE:
581 res = Py_True;
582 break;
583 default:
584 res = Py_False;
585 break;
586 }
587 Py_INCREF(res);
588 return res;
589 }
Guido van Rossuma1351fb2001-03-20 12:41:34 +0000590
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000591 t1 = PyTuple_New(3);
Benjamin Peterson2963fe02011-10-17 13:09:27 -0400592 if (t1 == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000593 return NULL;
Benjamin Peterson2963fe02011-10-17 13:09:27 -0400594 t2 = PyTuple_New(3);
595 if (t2 == NULL) {
596 Py_DECREF(t1);
597 return NULL;
598 }
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000599
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000600 PyTuple_SET_ITEM(t1, 0, ((PySliceObject *)v)->start);
601 PyTuple_SET_ITEM(t1, 1, ((PySliceObject *)v)->stop);
602 PyTuple_SET_ITEM(t1, 2, ((PySliceObject *)v)->step);
603 PyTuple_SET_ITEM(t2, 0, ((PySliceObject *)w)->start);
604 PyTuple_SET_ITEM(t2, 1, ((PySliceObject *)w)->stop);
605 PyTuple_SET_ITEM(t2, 2, ((PySliceObject *)w)->step);
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000606
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000607 res = PyObject_RichCompare(t1, t2, op);
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000608
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000609 PyTuple_SET_ITEM(t1, 0, NULL);
610 PyTuple_SET_ITEM(t1, 1, NULL);
611 PyTuple_SET_ITEM(t1, 2, NULL);
612 PyTuple_SET_ITEM(t2, 0, NULL);
613 PyTuple_SET_ITEM(t2, 1, NULL);
614 PyTuple_SET_ITEM(t2, 2, NULL);
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000615
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000616 Py_DECREF(t1);
617 Py_DECREF(t2);
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000618
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000619 return res;
Guido van Rossuma1351fb2001-03-20 12:41:34 +0000620}
Guido van Rossumf2d125b1996-07-30 16:45:48 +0000621
Benjamin Peterson2b601d32016-04-16 14:47:12 -0700622static int
623slice_traverse(PySliceObject *v, visitproc visit, void *arg)
624{
625 Py_VISIT(v->start);
626 Py_VISIT(v->stop);
627 Py_VISIT(v->step);
628 return 0;
629}
630
Guido van Rossumf2d125b1996-07-30 16:45:48 +0000631PyTypeObject PySlice_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000632 PyVarObject_HEAD_INIT(&PyType_Type, 0)
633 "slice", /* Name of this type */
634 sizeof(PySliceObject), /* Basic object size */
635 0, /* Item size for varobject */
636 (destructor)slice_dealloc, /* tp_dealloc */
637 0, /* tp_print */
638 0, /* tp_getattr */
639 0, /* tp_setattr */
640 0, /* tp_reserved */
641 (reprfunc)slice_repr, /* tp_repr */
642 0, /* tp_as_number */
643 0, /* tp_as_sequence */
644 0, /* tp_as_mapping */
Benjamin Peterson23d05c12010-10-17 20:13:05 +0000645 PyObject_HashNotImplemented, /* tp_hash */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000646 0, /* tp_call */
647 0, /* tp_str */
648 PyObject_GenericGetAttr, /* tp_getattro */
649 0, /* tp_setattro */
650 0, /* tp_as_buffer */
Benjamin Peterson2b601d32016-04-16 14:47:12 -0700651 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000652 slice_doc, /* tp_doc */
Benjamin Peterson2b601d32016-04-16 14:47:12 -0700653 (traverseproc)slice_traverse, /* tp_traverse */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000654 0, /* tp_clear */
655 slice_richcompare, /* tp_richcompare */
656 0, /* tp_weaklistoffset */
657 0, /* tp_iter */
658 0, /* tp_iternext */
659 slice_methods, /* tp_methods */
660 slice_members, /* tp_members */
661 0, /* tp_getset */
662 0, /* tp_base */
663 0, /* tp_dict */
664 0, /* tp_descr_get */
665 0, /* tp_descr_set */
666 0, /* tp_dictoffset */
667 0, /* tp_init */
668 0, /* tp_alloc */
669 slice_new, /* tp_new */
Guido van Rossumf2d125b1996-07-30 16:45:48 +0000670};