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 PyString_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 = PyInt_FromSsize_t(istart);
89
end = PyInt_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 (!PyInt_Check(r->step) && !PyLong_Check(r->step)) return -1;
110
*step = PyInt_AsSsize_t(r->step);
112
if (r->start == Py_None) {
113
*start = *step < 0 ? length-1 : 0;
115
if (!PyInt_Check(r->start) && !PyLong_Check(r->step)) return -1;
116
*start = PyInt_AsSsize_t(r->start);
117
if (*start < 0) *start += length;
119
if (r->stop == Py_None) {
120
*stop = *step < 0 ? -1 : length;
122
if (!PyInt_Check(r->stop) && !PyLong_Check(r->step)) return -1;
123
*stop = PyInt_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)
232
s = PyString_FromString("slice(");
233
comma = PyString_FromString(", ");
234
PyString_ConcatAndDel(&s, PyObject_Repr(r->start));
235
PyString_Concat(&s, comma);
236
PyString_ConcatAndDel(&s, PyObject_Repr(r->stop));
237
PyString_Concat(&s, comma);
238
PyString_ConcatAndDel(&s, PyObject_Repr(r->step));
239
PyString_ConcatAndDel(&s, PyString_FromString(")"));
244
static PyMemberDef slice_members[] = {
245
{"start", T_OBJECT, offsetof(PySliceObject, start), READONLY},
246
{"stop", T_OBJECT, offsetof(PySliceObject, stop), READONLY},
247
{"step", T_OBJECT, offsetof(PySliceObject, step), READONLY},
252
slice_indices(PySliceObject* self, PyObject* len)
254
Py_ssize_t ilen, start, stop, step, slicelength;
256
ilen = PyNumber_AsSsize_t(len, PyExc_OverflowError);
258
if (ilen == -1 && PyErr_Occurred()) {
262
if (PySlice_GetIndicesEx(self, ilen, &start, &stop,
263
&step, &slicelength) < 0) {
267
return Py_BuildValue("(nnn)", start, stop, step);
270
PyDoc_STRVAR(slice_indices_doc,
271
"S.indices(len) -> (start, stop, stride)\n\
273
Assuming a sequence of length len, calculate the start and stop\n\
274
indices, and the stride length of the extended slice described by\n\
275
S. Out of bounds indices are clipped in a manner consistent with the\n\
276
handling of normal slices.");
279
slice_reduce(PySliceObject* self)
281
return Py_BuildValue("O(OOO)", Py_TYPE(self), self->start, self->stop, self->step);
284
PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
286
static PyMethodDef slice_methods[] = {
287
{"indices", (PyCFunction)slice_indices,
288
METH_O, slice_indices_doc},
289
{"__reduce__", (PyCFunction)slice_reduce,
290
METH_NOARGS, reduce_doc},
295
slice_compare(PySliceObject *v, PySliceObject *w)
302
if (PyObject_Cmp(v->start, w->start, &result) < 0)
306
if (PyObject_Cmp(v->stop, w->stop, &result) < 0)
310
if (PyObject_Cmp(v->step, w->step, &result) < 0)
316
slice_hash(PySliceObject *v)
318
PyErr_SetString(PyExc_TypeError, "unhashable type");
322
PyTypeObject PySlice_Type = {
323
PyVarObject_HEAD_INIT(&PyType_Type, 0)
324
"slice", /* Name of this type */
325
sizeof(PySliceObject), /* Basic object size */
326
0, /* Item size for varobject */
327
(destructor)slice_dealloc, /* tp_dealloc */
331
(cmpfunc)slice_compare, /* tp_compare */
332
(reprfunc)slice_repr, /* tp_repr */
333
0, /* tp_as_number */
334
0, /* tp_as_sequence */
335
0, /* tp_as_mapping */
336
(hashfunc)slice_hash, /* tp_hash */
339
PyObject_GenericGetAttr, /* tp_getattro */
341
0, /* tp_as_buffer */
342
Py_TPFLAGS_DEFAULT, /* tp_flags */
343
slice_doc, /* tp_doc */
346
0, /* tp_richcompare */
347
0, /* tp_weaklistoffset */
350
slice_methods, /* tp_methods */
351
slice_members, /* tp_members */
355
0, /* tp_descr_get */
356
0, /* tp_descr_set */
357
0, /* tp_dictoffset */
360
slice_new, /* tp_new */