2
Written by Jim Hugunin and Chris Chase.
4
This includes both the singular ellipsis object and slice objects.
6
Guido, feel free to do whatever you want in the way of copyrights
11
Py_Ellipsis encodes the '...' rubber index token. It is similar to
12
the Py_NoneStruct in that there is no way to create other objects of
13
this type and there is exactly one in existence.
17
#include "structmember.h"
20
ellipsis_repr(PyObject *op)
22
return PyUnicode_FromString("Ellipsis");
25
static PyTypeObject PyEllipsis_Type = {
26
PyVarObject_HEAD_INIT(&PyType_Type, 0)
27
"ellipsis", /* tp_name */
30
0, /*never called*/ /* tp_dealloc */
35
ellipsis_repr, /* tp_repr */
37
0, /* tp_as_sequence */
38
0, /* tp_as_mapping */
42
PyObject_GenericGetAttr, /* tp_getattro */
45
Py_TPFLAGS_DEFAULT, /* tp_flags */
48
PyObject _Py_EllipsisObject = {
54
/* Slice object implementation
56
start, stop, and step are python objects with None indicating no
61
PySlice_New(PyObject *start, PyObject *stop, PyObject *step)
63
PySliceObject *obj = PyObject_New(PySliceObject, &PySlice_Type);
68
if (step == NULL) step = Py_None;
70
if (start == NULL) start = Py_None;
72
if (stop == NULL) stop = Py_None;
79
return (PyObject *) obj;
83
_PySlice_FromIndices(Py_ssize_t istart, Py_ssize_t istop)
85
PyObject *start, *end, *slice;
86
start = PyLong_FromSsize_t(istart);
89
end = PyLong_FromSsize_t(istop);
95
slice = PySlice_New(start, end, NULL);
102
PySlice_GetIndices(PySliceObject *r, Py_ssize_t length,
103
Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step)
105
/* XXX support long ints */
106
if (r->step == Py_None) {
109
if (!PyLong_Check(r->step)) return -1;
110
*step = PyLong_AsSsize_t(r->step);
112
if (r->start == Py_None) {
113
*start = *step < 0 ? length-1 : 0;
115
if (!PyLong_Check(r->start)) return -1;
116
*start = PyLong_AsSsize_t(r->start);
117
if (*start < 0) *start += length;
119
if (r->stop == Py_None) {
120
*stop = *step < 0 ? -1 : length;
122
if (!PyLong_Check(r->stop)) return -1;
123
*stop = PyLong_AsSsize_t(r->stop);
124
if (*stop < 0) *stop += length;
126
if (*stop > length) return -1;
127
if (*start >= length) return -1;
128
if (*step == 0) return -1;
133
PySlice_GetIndicesEx(PySliceObject *r, Py_ssize_t length,
134
Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step, Py_ssize_t *slicelength)
136
/* this is harder to get right than you might think */
138
Py_ssize_t defstart, defstop;
140
if (r->step == Py_None) {
144
if (!_PyEval_SliceIndex(r->step, step)) return -1;
146
PyErr_SetString(PyExc_ValueError,
147
"slice step cannot be zero");
152
defstart = *step < 0 ? length-1 : 0;
153
defstop = *step < 0 ? -1 : length;
155
if (r->start == Py_None) {
159
if (!_PyEval_SliceIndex(r->start, start)) return -1;
160
if (*start < 0) *start += length;
161
if (*start < 0) *start = (*step < 0) ? -1 : 0;
162
if (*start >= length)
163
*start = (*step < 0) ? length - 1 : length;
166
if (r->stop == Py_None) {
170
if (!_PyEval_SliceIndex(r->stop, stop)) return -1;
171
if (*stop < 0) *stop += length;
172
if (*stop < 0) *stop = (*step < 0) ? -1 : 0;
174
*stop = (*step < 0) ? length - 1 : length;
177
if ((*step < 0 && *stop >= *start)
178
|| (*step > 0 && *start >= *stop)) {
181
else if (*step < 0) {
182
*slicelength = (*stop-*start+1)/(*step)+1;
185
*slicelength = (*stop-*start-1)/(*step)+1;
192
slice_new(PyTypeObject *type, PyObject *args, PyObject *kw)
194
PyObject *start, *stop, *step;
196
start = stop = step = NULL;
198
if (!_PyArg_NoKeywords("slice()", kw))
201
if (!PyArg_UnpackTuple(args, "slice", 1, 3, &start, &stop, &step))
204
/* This swapping of stop and start is to maintain similarity with
210
return PySlice_New(start, stop, step);
213
PyDoc_STRVAR(slice_doc,
214
"slice([start,] stop[, step])\n\
216
Create a slice object. This is used for extended slicing (e.g. a[0:10:2]).");
219
slice_dealloc(PySliceObject *r)
228
slice_repr(PySliceObject *r)
230
return PyUnicode_FromFormat("slice(%R, %R, %R)", r->start, r->stop, r->step);
233
static PyMemberDef slice_members[] = {
234
{"start", T_OBJECT, offsetof(PySliceObject, start), READONLY},
235
{"stop", T_OBJECT, offsetof(PySliceObject, stop), READONLY},
236
{"step", T_OBJECT, offsetof(PySliceObject, step), READONLY},
241
slice_indices(PySliceObject* self, PyObject* len)
243
Py_ssize_t ilen, start, stop, step, slicelength;
245
ilen = PyNumber_AsSsize_t(len, PyExc_OverflowError);
247
if (ilen == -1 && PyErr_Occurred()) {
251
if (PySlice_GetIndicesEx(self, ilen, &start, &stop,
252
&step, &slicelength) < 0) {
256
return Py_BuildValue("(nnn)", start, stop, step);
259
PyDoc_STRVAR(slice_indices_doc,
260
"S.indices(len) -> (start, stop, stride)\n\
262
Assuming a sequence of length len, calculate the start and stop\n\
263
indices, and the stride length of the extended slice described by\n\
264
S. Out of bounds indices are clipped in a manner consistent with the\n\
265
handling of normal slices.");
268
slice_reduce(PySliceObject* self)
270
return Py_BuildValue("O(OOO)", Py_TYPE(self), self->start, self->stop, self->step);
273
PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
275
static PyMethodDef slice_methods[] = {
276
{"indices", (PyCFunction)slice_indices,
277
METH_O, slice_indices_doc},
278
{"__reduce__", (PyCFunction)slice_reduce,
279
METH_NOARGS, reduce_doc},
284
slice_richcompare(PyObject *v, PyObject *w, int op)
290
if (!PySlice_Check(v) || !PySlice_Check(w)) {
291
Py_INCREF(Py_NotImplemented);
292
return Py_NotImplemented;
296
/* XXX Do we really need this shortcut?
297
There's a unit test for it, but is that fair? */
314
if (t1 == NULL || t2 == NULL)
317
PyTuple_SET_ITEM(t1, 0, ((PySliceObject *)v)->start);
318
PyTuple_SET_ITEM(t1, 1, ((PySliceObject *)v)->stop);
319
PyTuple_SET_ITEM(t1, 2, ((PySliceObject *)v)->step);
320
PyTuple_SET_ITEM(t2, 0, ((PySliceObject *)w)->start);
321
PyTuple_SET_ITEM(t2, 1, ((PySliceObject *)w)->stop);
322
PyTuple_SET_ITEM(t2, 2, ((PySliceObject *)w)->step);
324
res = PyObject_RichCompare(t1, t2, op);
326
PyTuple_SET_ITEM(t1, 0, NULL);
327
PyTuple_SET_ITEM(t1, 1, NULL);
328
PyTuple_SET_ITEM(t1, 2, NULL);
329
PyTuple_SET_ITEM(t2, 0, NULL);
330
PyTuple_SET_ITEM(t2, 1, NULL);
331
PyTuple_SET_ITEM(t2, 2, NULL);
340
slice_hash(PySliceObject *v)
342
PyErr_SetString(PyExc_TypeError, "unhashable type");
346
PyTypeObject PySlice_Type = {
347
PyVarObject_HEAD_INIT(&PyType_Type, 0)
348
"slice", /* Name of this type */
349
sizeof(PySliceObject), /* Basic object size */
350
0, /* Item size for varobject */
351
(destructor)slice_dealloc, /* tp_dealloc */
356
(reprfunc)slice_repr, /* tp_repr */
357
0, /* tp_as_number */
358
0, /* tp_as_sequence */
359
0, /* tp_as_mapping */
360
(hashfunc)slice_hash, /* tp_hash */
363
PyObject_GenericGetAttr, /* tp_getattro */
365
0, /* tp_as_buffer */
366
Py_TPFLAGS_DEFAULT, /* tp_flags */
367
slice_doc, /* tp_doc */
370
slice_richcompare, /* tp_richcompare */
371
0, /* tp_weaklistoffset */
374
slice_methods, /* tp_methods */
375
slice_members, /* tp_members */
379
0, /* tp_descr_get */
380
0, /* tp_descr_set */
381
0, /* tp_dictoffset */
384
slice_new, /* tp_new */