Python-2.7.3/Objects/sliceobject.c

No issues found

  1 /*
  2 Written by Jim Hugunin and Chris Chase.
  3 
  4 This includes both the singular ellipsis object and slice objects.
  5 
  6 Guido, feel free to do whatever you want in the way of copyrights
  7 for this file.
  8 */
  9 
 10 /*
 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.
 14 */
 15 
 16 #include "Python.h"
 17 #include "structmember.h"
 18 
 19 static PyObject *
 20 ellipsis_repr(PyObject *op)
 21 {
 22     return PyString_FromString("Ellipsis");
 23 }
 24 
 25 PyTypeObject PyEllipsis_Type = {
 26     PyVarObject_HEAD_INIT(&PyType_Type, 0)
 27     "ellipsis",                         /* tp_name */
 28     0,                                  /* tp_basicsize */
 29     0,                                  /* tp_itemsize */
 30     0, /*never called*/                 /* tp_dealloc */
 31     0,                                  /* tp_print */
 32     0,                                  /* tp_getattr */
 33     0,                                  /* tp_setattr */
 34     0,                                  /* tp_compare */
 35     ellipsis_repr,                      /* tp_repr */
 36     0,                                  /* tp_as_number */
 37     0,                                  /* tp_as_sequence */
 38     0,                                  /* tp_as_mapping */
 39     0,                                  /* tp_hash */
 40     0,                                  /* tp_call */
 41     0,                                  /* tp_str */
 42     PyObject_GenericGetAttr,            /* tp_getattro */
 43     0,                                  /* tp_setattro */
 44     0,                                  /* tp_as_buffer */
 45     Py_TPFLAGS_DEFAULT,                 /* tp_flags */
 46 };
 47 
 48 PyObject _Py_EllipsisObject = {
 49     _PyObject_EXTRA_INIT
 50     1, &PyEllipsis_Type
 51 };
 52 
 53 
 54 /* Slice object implementation
 55 
 56    start, stop, and step are python objects with None indicating no
 57    index is present.
 58 */
 59 
 60 PyObject *
 61 PySlice_New(PyObject *start, PyObject *stop, PyObject *step)
 62 {
 63     PySliceObject *obj = PyObject_New(PySliceObject, &PySlice_Type);
 64 
 65     if (obj == NULL)
 66         return NULL;
 67 
 68     if (step == NULL) step = Py_None;
 69     Py_INCREF(step);
 70     if (start == NULL) start = Py_None;
 71     Py_INCREF(start);
 72     if (stop == NULL) stop = Py_None;
 73     Py_INCREF(stop);
 74 
 75     obj->step = step;
 76     obj->start = start;
 77     obj->stop = stop;
 78 
 79     return (PyObject *) obj;
 80 }
 81 
 82 PyObject *
 83 _PySlice_FromIndices(Py_ssize_t istart, Py_ssize_t istop)
 84 {
 85     PyObject *start, *end, *slice;
 86     start = PyInt_FromSsize_t(istart);
 87     if (!start)
 88         return NULL;
 89     end = PyInt_FromSsize_t(istop);
 90     if (!end) {
 91         Py_DECREF(start);
 92         return NULL;
 93     }
 94 
 95     slice = PySlice_New(start, end, NULL);
 96     Py_DECREF(start);
 97     Py_DECREF(end);
 98     return slice;
 99 }
100 
101 int
102 PySlice_GetIndices(PySliceObject *r, Py_ssize_t length,
103                    Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step)
104 {
105     /* XXX support long ints */
106     if (r->step == Py_None) {
107         *step = 1;
108     } else {
109         if (!PyInt_Check(r->step) && !PyLong_Check(r->step)) return -1;
110         *step = PyInt_AsSsize_t(r->step);
111     }
112     if (r->start == Py_None) {
113         *start = *step < 0 ? length-1 : 0;
114     } else {
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;
118     }
119     if (r->stop == Py_None) {
120         *stop = *step < 0 ? -1 : length;
121     } else {
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;
125     }
126     if (*stop > length) return -1;
127     if (*start >= length) return -1;
128     if (*step == 0) return -1;
129     return 0;
130 }
131 
132 int
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)
135 {
136     /* this is harder to get right than you might think */
137 
138     Py_ssize_t defstart, defstop;
139 
140     if (r->step == Py_None) {
141         *step = 1;
142     }
143     else {
144         if (!_PyEval_SliceIndex(r->step, step)) return -1;
145         if (*step == 0) {
146             PyErr_SetString(PyExc_ValueError,
147                             "slice step cannot be zero");
148             return -1;
149         }
150     }
151 
152     defstart = *step < 0 ? length-1 : 0;
153     defstop = *step < 0 ? -1 : length;
154 
155     if (r->start == Py_None) {
156         *start = defstart;
157     }
158     else {
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;
164     }
165 
166     if (r->stop == Py_None) {
167         *stop = defstop;
168     }
169     else {
170         if (!_PyEval_SliceIndex(r->stop, stop)) return -1;
171         if (*stop < 0) *stop += length;
172         if (*stop < 0) *stop = (*step < 0) ? -1 : 0;
173         if (*stop >= length)
174             *stop = (*step < 0) ? length - 1 : length;
175     }
176 
177     if ((*step < 0 && *stop >= *start)
178         || (*step > 0 && *start >= *stop)) {
179         *slicelength = 0;
180     }
181     else if (*step < 0) {
182         *slicelength = (*stop-*start+1)/(*step)+1;
183     }
184     else {
185         *slicelength = (*stop-*start-1)/(*step)+1;
186     }
187 
188     return 0;
189 }
190 
191 static PyObject *
192 slice_new(PyTypeObject *type, PyObject *args, PyObject *kw)
193 {
194     PyObject *start, *stop, *step;
195 
196     start = stop = step = NULL;
197 
198     if (!_PyArg_NoKeywords("slice()", kw))
199         return NULL;
200 
201     if (!PyArg_UnpackTuple(args, "slice", 1, 3, &start, &stop, &step))
202         return NULL;
203 
204     /* This swapping of stop and start is to maintain similarity with
205        range(). */
206     if (stop == NULL) {
207         stop = start;
208         start = NULL;
209     }
210     return PySlice_New(start, stop, step);
211 }
212 
213 PyDoc_STRVAR(slice_doc,
214 "slice([start,] stop[, step])\n\
215 \n\
216 Create a slice object.  This is used for extended slicing (e.g. a[0:10:2]).");
217 
218 static void
219 slice_dealloc(PySliceObject *r)
220 {
221     Py_DECREF(r->step);
222     Py_DECREF(r->start);
223     Py_DECREF(r->stop);
224     PyObject_Del(r);
225 }
226 
227 static PyObject *
228 slice_repr(PySliceObject *r)
229 {
230     PyObject *s, *comma;
231 
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(")"));
240     Py_DECREF(comma);
241     return s;
242 }
243 
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},
248     {0}
249 };
250 
251 static PyObject*
252 slice_indices(PySliceObject* self, PyObject* len)
253 {
254     Py_ssize_t ilen, start, stop, step, slicelength;
255 
256     ilen = PyNumber_AsSsize_t(len, PyExc_OverflowError);
257 
258     if (ilen == -1 && PyErr_Occurred()) {
259         return NULL;
260     }
261 
262     if (PySlice_GetIndicesEx(self, ilen, &start, &stop,
263                              &step, &slicelength) < 0) {
264         return NULL;
265     }
266 
267     return Py_BuildValue("(nnn)", start, stop, step);
268 }
269 
270 PyDoc_STRVAR(slice_indices_doc,
271 "S.indices(len) -> (start, stop, stride)\n\
272 \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.");
277 
278 static PyObject *
279 slice_reduce(PySliceObject* self)
280 {
281     return Py_BuildValue("O(OOO)", Py_TYPE(self), self->start, self->stop, self->step);
282 }
283 
284 PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
285 
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},
291     {NULL, NULL}
292 };
293 
294 static int
295 slice_compare(PySliceObject *v, PySliceObject *w)
296 {
297     int result = 0;
298 
299     if (v == w)
300         return 0;
301 
302     if (PyObject_Cmp(v->start, w->start, &result) < 0)
303         return -2;
304     if (result != 0)
305         return result;
306     if (PyObject_Cmp(v->stop, w->stop, &result) < 0)
307         return -2;
308     if (result != 0)
309         return result;
310     if (PyObject_Cmp(v->step, w->step, &result) < 0)
311         return -2;
312     return result;
313 }
314 
315 static long
316 slice_hash(PySliceObject *v)
317 {
318     PyErr_SetString(PyExc_TypeError, "unhashable type");
319     return -1L;
320 }
321 
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 */
328     0,                                          /* tp_print */
329     0,                                          /* tp_getattr */
330     0,                                          /* tp_setattr */
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 */
337     0,                                          /* tp_call */
338     0,                                          /* tp_str */
339     PyObject_GenericGetAttr,                    /* tp_getattro */
340     0,                                          /* tp_setattro */
341     0,                                          /* tp_as_buffer */
342     Py_TPFLAGS_DEFAULT,                         /* tp_flags */
343     slice_doc,                                  /* tp_doc */
344     0,                                          /* tp_traverse */
345     0,                                          /* tp_clear */
346     0,                                          /* tp_richcompare */
347     0,                                          /* tp_weaklistoffset */
348     0,                                          /* tp_iter */
349     0,                                          /* tp_iternext */
350     slice_methods,                              /* tp_methods */
351     slice_members,                              /* tp_members */
352     0,                                          /* tp_getset */
353     0,                                          /* tp_base */
354     0,                                          /* tp_dict */
355     0,                                          /* tp_descr_get */
356     0,                                          /* tp_descr_set */
357     0,                                          /* tp_dictoffset */
358     0,                                          /* tp_init */
359     0,                                          /* tp_alloc */
360     slice_new,                                  /* tp_new */
361 };