blob: 888069a433a5073728a956ea764163567cd99916 [file] [log] [blame]
Guido van Rossum12d12c51993-10-26 17:58:25 +00001/* Range object implementation */
2
Guido van Rossumc0b618a1997-05-02 03:12:38 +00003#include "Python.h"
Thomas Woutersefafcea2001-07-09 12:30:54 +00004
Guido van Rossum12d12c51993-10-26 17:58:25 +00005typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00006 PyObject_HEAD
7 long start;
8 long step;
9 long len;
Guido van Rossum12d12c51993-10-26 17:58:25 +000010} rangeobject;
11
Mark Dickinson009ae862009-11-15 12:31:13 +000012/* Return number of items in range (lo, hi, step). step != 0
13 * required. The result always fits in an unsigned long.
Raymond Hettingerc4c453f2002-06-05 23:12:45 +000014 */
Mark Dickinson009ae862009-11-15 12:31:13 +000015static unsigned long
Raymond Hettingerc4c453f2002-06-05 23:12:45 +000016get_len_of_range(long lo, long hi, long step)
17{
Mark Dickinson009ae862009-11-15 12:31:13 +000018 /* -------------------------------------------------------------
19 If step > 0 and lo >= hi, or step < 0 and lo <= hi, the range is empty.
20 Else for step > 0, if n values are in the range, the last one is
21 lo + (n-1)*step, which must be <= hi-1. Rearranging,
22 n <= (hi - lo - 1)/step + 1, so taking the floor of the RHS gives
23 the proper value. Since lo < hi in this case, hi-lo-1 >= 0, so
24 the RHS is non-negative and so truncation is the same as the
25 floor. Letting M be the largest positive long, the worst case
26 for the RHS numerator is hi=M, lo=-M-1, and then
27 hi-lo-1 = M-(-M-1)-1 = 2*M. Therefore unsigned long has enough
28 precision to compute the RHS exactly. The analysis for step < 0
29 is similar.
30 ---------------------------------------------------------------*/
31 assert(step != 0);
32 if (step > 0 && lo < hi)
Martin Panterca56dd42016-09-17 07:54:55 +000033 return 1UL + (hi - 1UL - lo) / step;
Mark Dickinson009ae862009-11-15 12:31:13 +000034 else if (step < 0 && lo > hi)
Martin Panterca56dd42016-09-17 07:54:55 +000035 return 1UL + (lo - 1UL - hi) / (0UL - step);
Mark Dickinson009ae862009-11-15 12:31:13 +000036 else
Martin Panterca56dd42016-09-17 07:54:55 +000037 return 0UL;
Raymond Hettingerc4c453f2002-06-05 23:12:45 +000038}
39
Mark Dickinson218a8ab2012-09-28 20:36:36 +010040/* Return a stop value suitable for reconstructing the xrange from
41 * a (start, stop, step) triple. Used in range_repr and range_reduce.
42 * Computes start + len * step, clipped to the range [LONG_MIN, LONG_MAX].
43 */
44static long
45get_stop_for_range(rangeobject *r)
46{
47 long last;
48
49 if (r->len == 0)
50 return r->start;
51
52 /* The tricky bit is avoiding overflow. We first compute the last entry in
53 the xrange, start + (len - 1) * step, which is guaranteed to lie within
54 the range of a long, and then add step to it. See the range_reverse
55 comments for an explanation of the casts below.
56 */
57 last = (long)(r->start + (unsigned long)(r->len - 1) * r->step);
58 if (r->step > 0)
59 return last > LONG_MAX - r->step ? LONG_MAX : last + r->step;
60 else
61 return last < LONG_MIN - r->step ? LONG_MIN : last + r->step;
62}
63
Raymond Hettingerc4c453f2002-06-05 23:12:45 +000064static PyObject *
65range_new(PyTypeObject *type, PyObject *args, PyObject *kw)
66{
Antoine Pitrouc83ea132010-05-09 14:46:46 +000067 rangeobject *obj;
68 long ilow = 0, ihigh = 0, istep = 1;
69 unsigned long n;
Raymond Hettingerc4c453f2002-06-05 23:12:45 +000070
Antoine Pitrouc83ea132010-05-09 14:46:46 +000071 if (!_PyArg_NoKeywords("xrange()", kw))
72 return NULL;
Georg Brandl02c42872005-08-26 06:42:30 +000073
Antoine Pitrouc83ea132010-05-09 14:46:46 +000074 if (PyTuple_Size(args) <= 1) {
75 if (!PyArg_ParseTuple(args,
76 "l;xrange() requires 1-3 int arguments",
77 &ihigh))
78 return NULL;
79 }
80 else {
81 if (!PyArg_ParseTuple(args,
82 "ll|l;xrange() requires 1-3 int arguments",
83 &ilow, &ihigh, &istep))
84 return NULL;
85 }
86 if (istep == 0) {
87 PyErr_SetString(PyExc_ValueError, "xrange() arg 3 must not be zero");
88 return NULL;
89 }
90 n = get_len_of_range(ilow, ihigh, istep);
91 if (n > (unsigned long)LONG_MAX || (long)n > PY_SSIZE_T_MAX) {
92 PyErr_SetString(PyExc_OverflowError,
93 "xrange() result has too many items");
94 return NULL;
95 }
Tim Petersfeec4532004-08-08 07:17:39 +000096
Antoine Pitrouc83ea132010-05-09 14:46:46 +000097 obj = PyObject_New(rangeobject, &PyRange_Type);
98 if (obj == NULL)
99 return NULL;
100 obj->start = ilow;
101 obj->len = (long)n;
102 obj->step = istep;
103 return (PyObject *) obj;
Raymond Hettingerc4c453f2002-06-05 23:12:45 +0000104}
105
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000106PyDoc_STRVAR(range_doc,
Chris Jerdonekad4b0002012-10-07 20:37:54 -0700107"xrange(stop) -> xrange object\n\
108xrange(start, stop[, step]) -> xrange object\n\
Raymond Hettingerc4c453f2002-06-05 23:12:45 +0000109\n\
110Like range(), but instead of returning a list, returns an object that\n\
Raymond Hettingerd2bef822002-12-11 07:14:03 +0000111generates the numbers in the range on demand. For looping, this is \n\
112slightly faster than range() and more memory efficient.");
Raymond Hettingerc4c453f2002-06-05 23:12:45 +0000113
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000114static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000115range_item(rangeobject *r, Py_ssize_t i)
Guido van Rossum12d12c51993-10-26 17:58:25 +0000116{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000117 if (i < 0 || i >= r->len) {
118 PyErr_SetString(PyExc_IndexError,
119 "xrange object index out of range");
120 return NULL;
121 }
122 /* do calculation entirely using unsigned longs, to avoid
123 undefined behaviour due to signed overflow. */
124 return PyInt_FromLong((long)(r->start + (unsigned long)i * r->step));
Guido van Rossum12d12c51993-10-26 17:58:25 +0000125}
126
Martin v. Löwis18e16552006-02-15 17:27:45 +0000127static Py_ssize_t
Fred Drake45cfbcc2000-07-09 06:21:27 +0000128range_length(rangeobject *r)
Guido van Rossum12d12c51993-10-26 17:58:25 +0000129{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000130 return (Py_ssize_t)(r->len);
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000131}
132
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000133static PyObject *
Fred Drake45cfbcc2000-07-09 06:21:27 +0000134range_repr(rangeobject *r)
Guido van Rossum12d12c51993-10-26 17:58:25 +0000135{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000136 PyObject *rtn;
Tim Petersd976ab72004-08-08 06:29:10 +0000137
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000138 if (r->start == 0 && r->step == 1)
139 rtn = PyString_FromFormat("xrange(%ld)",
Mark Dickinson218a8ab2012-09-28 20:36:36 +0100140 get_stop_for_range(r));
Tim Peters72d421b2000-08-04 03:05:40 +0000141
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000142 else if (r->step == 1)
143 rtn = PyString_FromFormat("xrange(%ld, %ld)",
144 r->start,
Mark Dickinson218a8ab2012-09-28 20:36:36 +0100145 get_stop_for_range(r));
Tim Peters72d421b2000-08-04 03:05:40 +0000146
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000147 else
148 rtn = PyString_FromFormat("xrange(%ld, %ld, %ld)",
149 r->start,
Mark Dickinson218a8ab2012-09-28 20:36:36 +0100150 get_stop_for_range(r),
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000151 r->step);
152 return rtn;
Thomas Woutersefafcea2001-07-09 12:30:54 +0000153}
154
Alexandre Vassalotti1f2f61a2008-06-10 03:34:53 +0000155/* Pickling support */
156static PyObject *
Alexandre Vassalotti602d8db2008-06-10 04:01:23 +0000157range_reduce(rangeobject *r, PyObject *args)
Alexandre Vassalotti1f2f61a2008-06-10 03:34:53 +0000158{
Mark Dickinson218a8ab2012-09-28 20:36:36 +0100159 return Py_BuildValue("(O(lll))", Py_TYPE(r),
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000160 r->start,
Mark Dickinson218a8ab2012-09-28 20:36:36 +0100161 get_stop_for_range(r),
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000162 r->step);
Alexandre Vassalotti1f2f61a2008-06-10 03:34:53 +0000163}
164
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000165static PySequenceMethods range_as_sequence = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000166 (lenfunc)range_length, /* sq_length */
167 0, /* sq_concat */
168 0, /* sq_repeat */
169 (ssizeargfunc)range_item, /* sq_item */
170 0, /* sq_slice */
Guido van Rossum12d12c51993-10-26 17:58:25 +0000171};
172
Jeremy Hylton938ace62002-07-17 16:30:39 +0000173static PyObject * range_iter(PyObject *seq);
Raymond Hettinger85c20a42003-11-06 14:06:48 +0000174static PyObject * range_reverse(PyObject *seq);
175
176PyDoc_STRVAR(reverse_doc,
177"Returns a reverse iterator.");
178
179static PyMethodDef range_methods[] = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000180 {"__reversed__", (PyCFunction)range_reverse, METH_NOARGS, reverse_doc},
181 {"__reduce__", (PyCFunction)range_reduce, METH_VARARGS},
182 {NULL, NULL} /* sentinel */
Raymond Hettinger85c20a42003-11-06 14:06:48 +0000183};
Raymond Hettinger48165d42002-06-05 20:08:48 +0000184
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000185PyTypeObject PyRange_Type = {
Benjamin Petersona72d15c2017-09-13 21:20:29 -0700186 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000187 "xrange", /* Name of this type */
188 sizeof(rangeobject), /* Basic object size */
189 0, /* Item size for varobject */
190 (destructor)PyObject_Del, /* tp_dealloc */
191 0, /* tp_print */
192 0, /* tp_getattr */
193 0, /* tp_setattr */
194 0, /* tp_compare */
195 (reprfunc)range_repr, /* tp_repr */
196 0, /* tp_as_number */
197 &range_as_sequence, /* tp_as_sequence */
198 0, /* tp_as_mapping */
199 0, /* tp_hash */
200 0, /* tp_call */
201 0, /* tp_str */
202 PyObject_GenericGetAttr, /* tp_getattro */
203 0, /* tp_setattro */
204 0, /* tp_as_buffer */
205 Py_TPFLAGS_DEFAULT, /* tp_flags */
206 range_doc, /* tp_doc */
207 0, /* tp_traverse */
208 0, /* tp_clear */
209 0, /* tp_richcompare */
210 0, /* tp_weaklistoffset */
211 range_iter, /* tp_iter */
212 0, /* tp_iternext */
213 range_methods, /* tp_methods */
214 0, /* tp_members */
215 0, /* tp_getset */
216 0, /* tp_base */
217 0, /* tp_dict */
218 0, /* tp_descr_get */
219 0, /* tp_descr_set */
220 0, /* tp_dictoffset */
221 0, /* tp_init */
222 0, /* tp_alloc */
223 range_new, /* tp_new */
Guido van Rossum12d12c51993-10-26 17:58:25 +0000224};
Raymond Hettinger48165d42002-06-05 20:08:48 +0000225
226/*********************** Xrange Iterator **************************/
227
228typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000229 PyObject_HEAD
230 long index;
231 long start;
232 long step;
233 long len;
Raymond Hettinger48165d42002-06-05 20:08:48 +0000234} rangeiterobject;
235
Raymond Hettinger85c20a42003-11-06 14:06:48 +0000236static PyObject *
Raymond Hettinger48165d42002-06-05 20:08:48 +0000237rangeiter_next(rangeiterobject *r)
238{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000239 if (r->index < r->len)
240 return PyInt_FromLong(r->start + (r->index++) * r->step);
241 return NULL;
Raymond Hettinger48165d42002-06-05 20:08:48 +0000242}
243
Raymond Hettinger6b27cda2005-09-24 21:23:05 +0000244static PyObject *
Raymond Hettingeref9bf402004-03-10 10:10:42 +0000245rangeiter_len(rangeiterobject *r)
246{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000247 return PyInt_FromLong(r->len - r->index);
Raymond Hettingeref9bf402004-03-10 10:10:42 +0000248}
249
Armin Rigof5b3e362006-02-11 21:32:43 +0000250PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
Raymond Hettingeref9bf402004-03-10 10:10:42 +0000251
Raymond Hettinger6b27cda2005-09-24 21:23:05 +0000252static PyMethodDef rangeiter_methods[] = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000253 {"__length_hint__", (PyCFunction)rangeiter_len, METH_NOARGS, length_hint_doc},
254 {NULL, NULL} /* sentinel */
Raymond Hettinger6b27cda2005-09-24 21:23:05 +0000255};
Raymond Hettingeref9bf402004-03-10 10:10:42 +0000256
Neal Norwitz56f46f82002-06-06 14:58:21 +0000257static PyTypeObject Pyrangeiter_Type = {
Benjamin Petersona72d15c2017-09-13 21:20:29 -0700258 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000259 "rangeiterator", /* tp_name */
260 sizeof(rangeiterobject), /* tp_basicsize */
261 0, /* tp_itemsize */
262 /* methods */
263 (destructor)PyObject_Del, /* tp_dealloc */
264 0, /* tp_print */
265 0, /* tp_getattr */
266 0, /* tp_setattr */
267 0, /* tp_compare */
268 0, /* tp_repr */
269 0, /* tp_as_number */
270 0, /* tp_as_sequence */
271 0, /* tp_as_mapping */
272 0, /* tp_hash */
273 0, /* tp_call */
274 0, /* tp_str */
275 PyObject_GenericGetAttr, /* tp_getattro */
276 0, /* tp_setattro */
277 0, /* tp_as_buffer */
278 Py_TPFLAGS_DEFAULT, /* tp_flags */
279 0, /* tp_doc */
280 0, /* tp_traverse */
281 0, /* tp_clear */
282 0, /* tp_richcompare */
283 0, /* tp_weaklistoffset */
284 PyObject_SelfIter, /* tp_iter */
285 (iternextfunc)rangeiter_next, /* tp_iternext */
286 rangeiter_methods, /* tp_methods */
287 0,
Raymond Hettinger48165d42002-06-05 20:08:48 +0000288};
Martin v. Löwis72d20672006-04-11 09:04:12 +0000289
290static PyObject *
291range_iter(PyObject *seq)
292{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000293 rangeiterobject *it;
Martin v. Löwis72d20672006-04-11 09:04:12 +0000294
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000295 if (!PyRange_Check(seq)) {
296 PyErr_BadInternalCall();
297 return NULL;
298 }
299 it = PyObject_New(rangeiterobject, &Pyrangeiter_Type);
300 if (it == NULL)
301 return NULL;
302 it->index = 0;
303 it->start = ((rangeobject *)seq)->start;
304 it->step = ((rangeobject *)seq)->step;
305 it->len = ((rangeobject *)seq)->len;
306 return (PyObject *)it;
Martin v. Löwis72d20672006-04-11 09:04:12 +0000307}
308
309static PyObject *
310range_reverse(PyObject *seq)
311{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000312 rangeiterobject *it;
313 long start, step, len;
Martin v. Löwis72d20672006-04-11 09:04:12 +0000314
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000315 if (!PyRange_Check(seq)) {
316 PyErr_BadInternalCall();
317 return NULL;
318 }
319 it = PyObject_New(rangeiterobject, &Pyrangeiter_Type);
320 if (it == NULL)
321 return NULL;
Martin v. Löwis72d20672006-04-11 09:04:12 +0000322
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000323 start = ((rangeobject *)seq)->start;
324 step = ((rangeobject *)seq)->step;
325 len = ((rangeobject *)seq)->len;
Martin v. Löwis72d20672006-04-11 09:04:12 +0000326
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000327 it->index = 0;
328 it->len = len;
329 /* the casts below guard against signed overflow by turning it
330 into unsigned overflow instead. The correctness of this
331 code still depends on conversion from unsigned long to long
332 wrapping modulo ULONG_MAX+1, which isn't guaranteed (see
333 C99 6.3.1.3p3) but seems to hold in practice for all
334 platforms we're likely to meet.
Mark Dickinson009ae862009-11-15 12:31:13 +0000335
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000336 If step == LONG_MIN then we still end up with LONG_MIN
337 after negation; but this works out, since we've still got
338 the correct value modulo ULONG_MAX+1, and the range_item
339 calculation is also done modulo ULONG_MAX+1.
340 */
341 it->start = (long)(start + (unsigned long)(len-1) * step);
342 it->step = (long)(0UL-step);
Martin v. Löwis72d20672006-04-11 09:04:12 +0000343
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000344 return (PyObject *)it;
Martin v. Löwis72d20672006-04-11 09:04:12 +0000345}