Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(9)

Side by Side Diff: Objects/rangeobject.c

Issue 602: range: lean and mean (Closed) SVN Base: http://svn.python.org/view/*checkout*/python/branches/py3k/
Patch Set: address more concerns Created 1 year, 7 months ago , Downloaded from: http://bugs.python.org/file10183/range_lean_and_mean5.patch
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* Range object implementation */ 1 /* Range object implementation */
2 2
3 #include "Python.h" 3 #include "Python.h"
4 #include "structmember.h"
4 5
5 /* Support objects whose length is > PY_SSIZE_T_MAX. 6 /* Support objects whose length is > PY_SSIZE_T_MAX.
6 7
7 This could be sped up for small PyLongs if they fit in an Py_ssize_t. 8 This could be sped up for small PyLongs if they fit in an Py_ssize_t.
8 This only matters on Win64. Though we could use PY_LONG_LONG which 9 This only matters on Win64. Though we could use PY_LONG_LONG which
9 would presumably help perf. 10 would presumably help perf.
10 */ 11 */
11 12
12 typedef struct { 13 typedef struct {
13 PyObject_HEAD 14 PyObject_HEAD
14 PyObject *start; 15 PyObject *start;
15 PyObject *stop; 16 PyObject *stop;
16 PyObject *step; 17 PyObject *step;
18 PyObject *length;
17 } rangeobject; 19 } rangeobject;
18 20
19 /* Helper function for validating step. Always returns a new reference or 21 /* Helper function for validating step. Always returns a new reference or
20 NULL on error. 22 NULL on error.
21 */ 23 */
22 static PyObject * 24 static PyObject *
23 validate_step(PyObject *step) 25 validate_step(PyObject *step)
24 { 26 {
25 /* No step specified, use a step of 1. */ 27 /* No step specified, use a step of 1. */
26 if (!step) 28 if (!step)
27 return PyLong_FromLong(1); 29 return PyLong_FromLong(1);
28 30
29 step = PyNumber_Index(step); 31 step = PyNumber_Index(step);
30 if (step) { 32 if (step) {
31 Py_ssize_t istep = PyNumber_AsSsize_t(step, NULL); 33 Py_ssize_t istep = PyNumber_AsSsize_t(step, NULL);
32 if (istep == -1 && PyErr_Occurred()) { 34 if (istep == -1 && PyErr_Occurred()) {
33 /* Ignore OverflowError, we know the value isn't 0. */ 35 /* Ignore OverflowError, we know the value isn't 0. */
34 PyErr_Clear(); 36 PyErr_Clear();
35 } 37 }
36 else if (istep == 0) { 38 else if (istep == 0) {
37 PyErr_SetString(PyExc_ValueError, 39 PyErr_SetString(PyExc_ValueError,
38 "range() arg 3 must not be zero"); 40 "range() arg 3 must not be zero");
39 Py_CLEAR(step); 41 Py_CLEAR(step);
40 } 42 }
41 } 43 }
42 44
43 return step; 45 return step;
44 } 46 }
47
48 static PyObject* range_compute_length(PyObject *start,
49 PyObject *stop, PyObject *step);
45 50
46 /* XXX(nnorwitz): should we error check if the user passes any empty ranges? 51 /* XXX(nnorwitz): should we error check if the user passes any empty ranges?
47 range(-10) 52 range(-10)
48 range(0, -5) 53 range(0, -5)
49 range(0, 5, -1) 54 range(0, 5, -1)
50 */ 55 */
51 static PyObject * 56 static PyObject *
52 range_new(PyTypeObject *type, PyObject *args, PyObject *kw) 57 range_new(PyTypeObject *type, PyObject *args, PyObject *kw)
53 { 58 {
54 rangeobject *obj = NULL; 59 rangeobject *obj = NULL;
55 PyObject *start = NULL, *stop = NULL, *step = NULL; 60 PyObject *start = NULL, *stop = NULL, *step = NULL, *length = NULL;
56 61
57 if (!_PyArg_NoKeywords("range()", kw)) 62 if (!_PyArg_NoKeywords("range()", kw))
58 return NULL; 63 return NULL;
59 64
60 if (PyTuple_Size(args) <= 1) { 65 if (PyTuple_Size(args) <= 1) {
61 if (!PyArg_UnpackTuple(args, "range", 1, 1, &stop)) 66 if (!PyArg_UnpackTuple(args, "range", 1, 1, &stop))
62 goto Fail; 67 goto Fail;
63 stop = PyNumber_Index(stop); 68 stop = PyNumber_Index(stop);
64 if (!stop) 69 if (!stop)
65 goto Fail; 70 goto Fail;
66 start = PyLong_FromLong(0); 71 start = PyLong_FromLong(0);
67 step = PyLong_FromLong(1); 72 step = PyLong_FromLong(1);
68 if (!start || !step) 73 if (!start || !step)
69 goto Fail; 74 goto Fail;
70 } 75 }
71 else { 76 else {
72 if (!PyArg_UnpackTuple(args, "range", 2, 3, 77 if (!PyArg_UnpackTuple(args, "range", 2, 3,
73 &start, &stop, &step)) 78 &start, &stop, &step))
74 goto Fail; 79 goto Fail;
75 80
76 /* Convert borrowed refs to owned refs */ 81 /* Convert borrowed refs to owned refs */
77 start = PyNumber_Index(start); 82 start = PyNumber_Index(start);
78 stop = PyNumber_Index(stop); 83 stop = PyNumber_Index(stop);
79 step = validate_step(step); 84 step = validate_step(step);
80 if (!start || !stop || !step) 85 if (!start || !stop || !step)
81 goto Fail; 86 goto Fail;
82 } 87 }
83 88
89 length = range_compute_length(start, stop, step);
90 if (length == NULL)
91 goto Fail;
84 obj = PyObject_New(rangeobject, &PyRange_Type); 92 obj = PyObject_New(rangeobject, &PyRange_Type);
85 if (obj == NULL) 93 if (obj == NULL)
86 goto Fail; 94 goto Fail;
87 obj->start = start; 95 obj->start = start;
88 obj->stop = stop; 96 obj->stop = stop;
89 obj->step = step; 97 obj->step = step;
98 obj->length = length;
90 return (PyObject *) obj; 99 return (PyObject *) obj;
91 100
92 Fail: 101 Fail:
93 Py_XDECREF(start); 102 Py_XDECREF(start);
94 Py_XDECREF(stop); 103 Py_XDECREF(stop);
95 Py_XDECREF(step); 104 Py_XDECREF(step);
105 Py_XDECREF(length);
96 return NULL; 106 return NULL;
97 } 107 }
98 108
99 PyDoc_STRVAR(range_doc, 109 PyDoc_STRVAR(range_doc,
100 "range([start,] stop[, step]) -> range object\n\ 110 "range([start,] stop[, step]) -> range object\n\
101 \n\ 111 \n\
102 Returns an iterator that generates the numbers in the range on demand."); 112 Return an arithmetic progression of numbers from start "
113 "to stop (exclusive) by step.");
103 114
104 static void 115 static void
105 range_dealloc(rangeobject *r) 116 range_dealloc(rangeobject *r)
106 { 117 {
107 Py_DECREF(r->start); 118 Py_DECREF(r->start);
108 Py_DECREF(r->stop); 119 Py_DECREF(r->stop);
109 Py_DECREF(r->step); 120 Py_DECREF(r->step);
121 Py_DECREF(r->length);
110 PyObject_Del(r); 122 PyObject_Del(r);
111 } 123 }
112 124
113 /* Return number of items in range (lo, hi, step), when arguments are 125 /*Return number of items in range (lo, hi, step), when arguments are
114 * PyInt or PyLong objects. step > 0 required. Return a value < 0 if 126 * PyLong objects. step > 0 required. Return a PyLong with the length.
115 * & only if the true value is too large to fit in a signed long. 127 * Return NULL when there is an error.*/
116 * Arguments MUST return 1 with either PyLong_Check() or 128 static PyObject *
117 * PyLong_Check(). Return -1 when there is an error. 129 range_compute_length(PyObject *start, PyObject *stop, PyObject *step)
118 */
119 static PyObject*
120 range_length_obj(rangeobject *r)
121 { 130 {
122 /* ------------------------------------------------------------- 131 /* -------------------------------------------------------------
123 Algorithm is equal to that of get_len_of_range(), but it operates 132 Algorithm is equal to that of get_len_of_range(), but it operates
124 on PyObjects (which are assumed to be PyLong or PyInt objects). 133 on PyObjects (which are assumed to be PyLong or PyInt objects).
125 ---------------------------------------------------------------*/ 134 ---------------------------------------------------------------*/
126 int cmp_result, cmp_call; 135 int cmp_result, cmp_call;
127 PyObject *lo, *hi; 136 PyObject *lo, *hi;
128 PyObject *step = NULL;
129 PyObject *diff = NULL; 137 PyObject *diff = NULL;
130 PyObject *one = NULL; 138 PyObject *one = NULL;
131 PyObject *tmp1 = NULL, *tmp2 = NULL, *result; 139 PyObject *tmp1 = NULL, *tmp2 = NULL, *result;
132 /* holds sub-expression evaluations */ 140 /* holds sub-expression evaluations */
133 141
134 PyObject *zero = PyLong_FromLong(0); 142 PyObject *zero = PyLong_FromLong(0);
135 if (zero == NULL) 143 if (zero == NULL)
136 return NULL; 144 return NULL;
137 cmp_call = PyObject_Cmp(r->step, zero, &cmp_result); 145 cmp_call = PyObject_Cmp(step, zero, &cmp_result);
138 Py_DECREF(zero); 146 Py_DECREF(zero);
139 if (cmp_call == -1) 147 if (cmp_call == -1)
140 return NULL; 148 return NULL;
141 149
142 assert(cmp_result != 0); 150 assert(cmp_result != 0);
143 if (cmp_result > 0) { 151 if (cmp_result > 0) {
144 lo = r->start; 152 lo = start;
145 hi = r->stop; 153 hi = stop;
146 step = r->step;
147 Py_INCREF(step); 154 Py_INCREF(step);
148 } else { 155 } else {
149 lo = r->stop; 156 lo = stop;
150 hi = r->start; 157 hi = start;
151 step = PyNumber_Negative(r->step); 158 step = PyNumber_Negative(step);
152 if (!step) 159 if (!step)
153 return NULL; 160 goto Fail;
154 } 161 }
155 162
156 /* if (lo >= hi), return length of 0. */ 163 /* if (lo >= hi), return length of 0. */
157 if (PyObject_Compare(lo, hi) >= 0) { 164 if (PyObject_Compare(lo, hi) >= 0) {
158 Py_XDECREF(step); 165 Py_XDECREF(step);
159 return PyLong_FromLong(0); 166 return PyLong_FromLong(0);
160 } 167 }
161 168
162 if ((one = PyLong_FromLong(1L)) == NULL) 169 if ((one = PyLong_FromLong(1L)) == NULL)
163 goto Fail; 170 goto Fail;
(...skipping 22 matching lines...) Expand all
186 Py_XDECREF(diff); 193 Py_XDECREF(diff);
187 Py_XDECREF(step); 194 Py_XDECREF(step);
188 Py_XDECREF(tmp1); 195 Py_XDECREF(tmp1);
189 Py_XDECREF(one); 196 Py_XDECREF(one);
190 return NULL; 197 return NULL;
191 } 198 }
192 199
193 static Py_ssize_t 200 static Py_ssize_t
194 range_length(rangeobject *r) 201 range_length(rangeobject *r)
195 { 202 {
196 PyObject *len = range_length_obj(r); 203 return PyLong_AsSsize_t(r->length);
197 Py_ssize_t result = -1;
198 if (len) {
199 result = PyLong_AsSsize_t(len);
200 Py_DECREF(len);
201 }
202 return result;
203 } 204 }
204 205
205 /* range(...)[x] is necessary for: seq[:] = range(...) */
206
207 static PyObject *
208 range_item(rangeobject *r, Py_ssize_t i)
209 {
210 Py_ssize_t len = range_length(r);
211 PyObject *rem, *incr, *result;
212
213 /* XXX(nnorwitz): should negative indices be supported? */
214 /* XXX(nnorwitz): should support range[x] where x > PY_SSIZE_T_MAX? */
215 if (i < 0 || i >= len) {
216 if (!PyErr_Occurred())
217 PyErr_SetString(PyExc_IndexError,
218 "range object index out of range");
219 return NULL;
220 }
221
222 /* XXX(nnorwitz): optimize for short ints. */
223 rem = PyLong_FromSsize_t(i);
224 if (!rem)
225 return NULL;
226 incr = PyNumber_Multiply(rem, r->step);
227 Py_DECREF(rem);
228 if (!incr)
229 return NULL;
230 result = PyNumber_Add(r->start, incr);
231 Py_DECREF(incr);
232 return result;
233 }
234 206
235 static PyObject * 207 static PyObject *
236 range_repr(rangeobject *r) 208 range_repr(rangeobject *r)
237 { 209 {
238 Py_ssize_t istep; 210 Py_ssize_t istep;
239 211
240 /* Check for special case values for printing. We don't always 212 /* Check for special case values for printing. We don't always
241 need the step value. We don't care about errors 213 need the step value. We don't care about errors
242 (it means overflow), so clear the errors. */ 214 (it means overflow), so clear the errors. */
243 istep = PyNumber_AsSsize_t(r->step, NULL); 215 istep = PyNumber_AsSsize_t(r->step, NULL);
244 if (istep != 1 || (istep == -1 && PyErr_Occurred())) { 216 if (istep != 1 || (istep == -1 && PyErr_Occurred())) {
245 PyErr_Clear(); 217 PyErr_Clear();
246 } 218 }
247 219
248 if (istep == 1) 220 if (istep == 1)
249 return PyUnicode_FromFormat("range(%R, %R)", r->start, r->stop); 221 return PyUnicode_FromFormat("range(%R, %R)", r->start, r->stop);
250 else 222 else
251 return PyUnicode_FromFormat("range(%R, %R, %R)", 223 return PyUnicode_FromFormat("range(%R, %R, %R)",
252 r->start, r->stop, r->step); 224 r->start, r->stop, r->step);
253 } 225 }
254 226
255 static PySequenceMethods range_as_sequence = { 227 static PyMemberDef range_members[] = {
256 (lenfunc)range_length,» /* sq_length */ 228 {"start", T_OBJECT, offsetof(rangeobject, start), READONLY},
257 0,» » » /* sq_concat */ 229 {"stop", T_OBJECT, offsetof(rangeobject, stop), READONLY},
258 0,» » » /* sq_repeat */ 230 {"step", T_OBJECT, offsetof(rangeobject, step), READONLY},
259 (ssizeargfunc)range_item, /* sq_item */ 231 {0}
260 0,» » » /* sq_slice */
261 }; 232 };
262 233
263 static PyObject * range_iter(PyObject *seq); 234 static PyObject * range_iter(PyObject *seq);
264 static PyObject * range_reverse(PyObject *seq); 235 static PyObject * range_reverse(PyObject *seq);
265 236
266 PyDoc_STRVAR(reverse_doc, 237 PyDoc_STRVAR(reverse_doc,
267 "Returns a reverse iterator."); 238 "Returns a reverse iterator.");
239
240 static PySequenceMethods range_as_sequence = {
241 (lenfunc)range_length, /* sq_length */
242 0, /* sq_concat */
243 0, /* sq_repeat */
244 0, /* sq_item */
245 0, /* sq_slice */
246 0, /* sq_ass_item */
247 0, /* sq_ass_slice */
248 0, /* sq_contains */
249 0, /* sq_inplace_concat */
250 0, /* sq_inplace_repeat */
251 };
268 252
269 static PyMethodDef range_methods[] = { 253 static PyMethodDef range_methods[] = {
270 {"__reversed__", (PyCFunction)range_reverse, METH_NOARGS, 254 {"__reversed__", (PyCFunction)range_reverse, METH_NOARGS,
271 reverse_doc}, 255 reverse_doc},
272 {NULL, NULL} /* sentinel */ 256 {NULL, NULL} /* sentinel */
273 }; 257 };
274 258
275 PyTypeObject PyRange_Type = { 259 PyTypeObject PyRange_Type = {
276 PyVarObject_HEAD_INIT(&PyType_Type, 0) 260 PyVarObject_HEAD_INIT(&PyType_Type, 0)
277 "range", /* Name of this type */ 261 "range", /* Name of this type */
278 sizeof(rangeobject), /* Basic object size */ 262 sizeof(rangeobject), /* Basic object size */
279 0, /* Item size for varobject */ 263 0, /* Item size for varobject */
280 (destructor)range_dealloc, /* tp_dealloc */ 264 (destructor)range_dealloc, /* tp_dealloc */
281 0, /* tp_print */ 265 0, /* tp_print */
282 0, /* tp_getattr */ 266 0, /* tp_getattr */
283 0, /* tp_setattr */ 267 0, /* tp_setattr */
284 0, /* tp_compare */ 268 0, /* tp_compare */
285 (reprfunc)range_repr, /* tp_repr */ 269 (reprfunc)range_repr, /* tp_repr */
286 0, /* tp_as_number */ 270 0, /* tp_as_number */
287 » &range_as_sequence,» /* tp_as_sequence */ 271 » &range_as_sequence, /* tp_as_sequence */
288 » 0,» » » /* tp_as_mapping */ 272 » 0, /* tp_as_mapping */
289 0, /* tp_hash */ 273 0, /* tp_hash */
290 0, /* tp_call */ 274 0, /* tp_call */
291 0, /* tp_str */ 275 0, /* tp_str */
292 PyObject_GenericGetAttr, /* tp_getattro */ 276 PyObject_GenericGetAttr, /* tp_getattro */
293 0, /* tp_setattro */ 277 0, /* tp_setattro */
294 0, /* tp_as_buffer */ 278 0, /* tp_as_buffer */
295 Py_TPFLAGS_DEFAULT, /* tp_flags */ 279 Py_TPFLAGS_DEFAULT, /* tp_flags */
296 range_doc, /* tp_doc */ 280 range_doc, /* tp_doc */
297 0, /* tp_traverse */ 281 0, /* tp_traverse */
298 0, /* tp_clear */ 282 0, /* tp_clear */
299 0, /* tp_richcompare */ 283 0, /* tp_richcompare */
300 0, /* tp_weaklistoffset */ 284 0, /* tp_weaklistoffset */
301 range_iter, /* tp_iter */ 285 range_iter, /* tp_iter */
302 0, /* tp_iternext */ 286 0, /* tp_iternext */
303 range_methods, /* tp_methods */ 287 range_methods, /* tp_methods */
304 » 0,» » » /* tp_members */ 288 » range_members, /* tp_members */
305 » 0,» » » /* tp_getset */ 289 » 0, /* tp_getset */
306 0, /* tp_base */ 290 0, /* tp_base */
307 0, /* tp_dict */ 291 0, /* tp_dict */
308 0, /* tp_descr_get */ 292 0, /* tp_descr_get */
309 0, /* tp_descr_set */ 293 0, /* tp_descr_set */
310 0, /* tp_dictoffset */ 294 0, /* tp_dictoffset */
311 0, /* tp_init */ 295 0, /* tp_init */
312 0, /* tp_alloc */ 296 0, /* tp_alloc */
313 range_new, /* tp_new */ 297 range_new, /* tp_new */
314 }; 298 };
315 299
(...skipping 24 matching lines...) Expand all
340 rangeiter_len(rangeiterobject *r) 324 rangeiter_len(rangeiterobject *r)
341 { 325 {
342 return PyLong_FromLong(r->len - r->index); 326 return PyLong_FromLong(r->len - r->index);
343 } 327 }
344 328
345 typedef struct { 329 typedef struct {
346 PyObject_HEAD 330 PyObject_HEAD
347 PyObject *index; 331 PyObject *index;
348 PyObject *start; 332 PyObject *start;
349 PyObject *step; 333 PyObject *step;
350 PyObject *len; 334 PyObject *length;
351 } longrangeiterobject; 335 } longrangeiterobject;
352 336
353 static PyObject * 337 static PyObject *
354 longrangeiter_len(longrangeiterobject *r, PyObject *no_args) 338 longrangeiter_len(longrangeiterobject *r, PyObject *no_args)
355 { 339 {
356 return PyNumber_Subtract(r->len, r->index); 340 return PyNumber_Subtract(r->length, r->index);
357 } 341 }
358 342
359 static PyObject *rangeiter_new(PyTypeObject *, PyObject *args, PyObject *kw); 343 static PyObject *rangeiter_new(PyTypeObject *, PyObject *args, PyObject *kw);
360 344
361 PyDoc_STRVAR(length_hint_doc, 345 PyDoc_STRVAR(length_hint_doc,
362 "Private method returning an estimate of len(list(it))."); 346 "Private method returning an estimate of len(list(it)).");
363 347
364 static PyMethodDef rangeiter_methods[] = { 348 static PyMethodDef rangeiter_methods[] = {
365 {"__length_hint__", (PyCFunction)rangeiter_len, METH_NOARGS, 349 {"__length_hint__", (PyCFunction)rangeiter_len, METH_NOARGS,
366 length_hint_doc}, 350 length_hint_doc},
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
474 length_hint_doc}, 458 length_hint_doc},
475 {NULL, NULL} /* sentinel */ 459 {NULL, NULL} /* sentinel */
476 }; 460 };
477 461
478 static void 462 static void
479 longrangeiter_dealloc(longrangeiterobject *r) 463 longrangeiter_dealloc(longrangeiterobject *r)
480 { 464 {
481 Py_XDECREF(r->index); 465 Py_XDECREF(r->index);
482 Py_XDECREF(r->start); 466 Py_XDECREF(r->start);
483 Py_XDECREF(r->step); 467 Py_XDECREF(r->step);
484 Py_XDECREF(r->len); 468 Py_XDECREF(r->length);
485 PyObject_Del(r); 469 PyObject_Del(r);
486 } 470 }
487 471
488 static PyObject * 472 static PyObject *
489 longrangeiter_next(longrangeiterobject *r) 473 longrangeiter_next(longrangeiterobject *r)
490 { 474 {
491 PyObject *one, *product, *new_index, *result; 475 PyObject *one, *product, *new_index, *result;
492 if (PyObject_RichCompareBool(r->index, r->len, Py_LT) != 1) 476 if (PyObject_RichCompareBool(r->index, r->length, Py_LT) != 1)
493 return NULL; 477 return NULL;
494 478
495 one = PyLong_FromLong(1); 479 one = PyLong_FromLong(1);
496 if (!one) 480 if (!one)
497 return NULL; 481 return NULL;
498 482
499 product = PyNumber_Multiply(r->index, r->step); 483 product = PyNumber_Multiply(r->index, r->step);
500 if (!product) { 484 if (!product) {
501 Py_DECREF(one); 485 Py_DECREF(one);
502 return NULL; 486 return NULL;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
550 (iternextfunc)longrangeiter_next, /* tp_iternext */ 534 (iternextfunc)longrangeiter_next, /* tp_iternext */
551 longrangeiter_methods, /* tp_methods */ 535 longrangeiter_methods, /* tp_methods */
552 0, 536 0,
553 }; 537 };
554 538
555 static PyObject * 539 static PyObject *
556 range_iter(PyObject *seq) 540 range_iter(PyObject *seq)
557 { 541 {
558 rangeobject *r = (rangeobject *)seq; 542 rangeobject *r = (rangeobject *)seq;
559 longrangeiterobject *it; 543 longrangeiterobject *it;
560 PyObject *tmp, *len;
561 long lstart, lstop, lstep; 544 long lstart, lstop, lstep;
562 545
563 assert(PyRange_Check(seq)); 546 assert(PyRange_Check(seq));
564 547
565 /* If all three fields convert to long, use the int version */ 548 /* If all three fields convert to long, use the int version */
566 lstart = PyLong_AsLong(r->start); 549 lstart = PyLong_AsLong(r->start);
567 if (lstart != -1 || !PyErr_Occurred()) { 550 if (lstart != -1 || !PyErr_Occurred()) {
568 lstop = PyLong_AsLong(r->stop); 551 lstop = PyLong_AsLong(r->stop);
569 if (lstop != -1 || !PyErr_Occurred()) { 552 if (lstop != -1 || !PyErr_Occurred()) {
570 lstep = PyLong_AsLong(r->step); 553 lstep = PyLong_AsLong(r->step);
571 if (lstep != -1 || !PyErr_Occurred()) 554 if (lstep != -1 || !PyErr_Occurred())
572 return int_range_iter(lstart, lstop, lstep); 555 return int_range_iter(lstart, lstop, lstep);
573 } 556 }
574 } 557 }
575 /* Some conversion failed, so there is an error set. Clear it, 558 /* Some conversion failed, so there is an error set. Clear it,
576 and try again with a long range. */ 559 and try again with a long range. */
577 PyErr_Clear(); 560 PyErr_Clear();
578 561
579 it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type); 562 it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type);
580 if (it == NULL) 563 if (it == NULL)
581 return NULL; 564 return NULL;
582 565
583 /* Do all initialization here, so we can DECREF on failure. */ 566 /* Do all initialization here, so we can DECREF on failure. */
584 it->start = r->start; 567 it->start = r->start;
585 it->step = r->step; 568 it->step = r->step;
586 Py_INCREF(it->start); 569 Py_INCREF(it->start);
587 Py_INCREF(it->step); 570 Py_INCREF(it->step);
588 571
589 it->len = it->index = NULL; 572 Py_INCREF(r->length);
590 573 it->length = r->length;
591 /* Calculate length: (r->stop - r->start) / r->step */
592 tmp = PyNumber_Subtract(r->stop, r->start);
593 if (!tmp)
594 goto create_failure;
595 len = PyNumber_FloorDivide(tmp, r->step);
596 Py_DECREF(tmp);
597 if (!len)
598 goto create_failure;
599 it->len = len;
600 it->index = PyLong_FromLong(0); 574 it->index = PyLong_FromLong(0);
601 if (!it->index) 575 if (it->index == NULL)
602 goto create_failure; 576 goto create_failure;
603 577
604 return (PyObject *)it; 578 return (PyObject *)it;
605 579
606 create_failure: 580 create_failure:
607 Py_DECREF(it); 581 Py_DECREF(it);
608 return NULL; 582 return NULL;
609 } 583 }
610 584
611 static PyObject * 585 static PyObject *
(...skipping 28 matching lines...) Expand all
640 } 614 }
641 } 615 }
642 } 616 }
643 PyErr_Clear(); 617 PyErr_Clear();
644 618
645 it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type); 619 it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type);
646 if (it == NULL) 620 if (it == NULL)
647 return NULL; 621 return NULL;
648 622
649 /* start + (len - 1) * step */ 623 /* start + (len - 1) * step */
650 len = range_length_obj(range); 624 Py_INCREF(range->length);
651 if (!len) 625 len = range->length;
652 goto create_failure;
653 626
654 one = PyLong_FromLong(1); 627 one = PyLong_FromLong(1);
655 if (!one) 628 if (!one)
656 goto create_failure; 629 goto create_failure;
657 630
658 diff = PyNumber_Subtract(len, one); 631 diff = PyNumber_Subtract(len, one);
659 Py_DECREF(one); 632 Py_DECREF(one);
660 if (!diff) 633 if (!diff)
661 goto create_failure; 634 goto create_failure;
662 635
663 product = PyNumber_Multiply(len, range->step); 636 product = PyNumber_Multiply(len, range->step);
664 if (!product) 637 if (!product)
665 goto create_failure; 638 goto create_failure;
666 639
667 sum = PyNumber_Add(range->start, product); 640 sum = PyNumber_Add(range->start, product);
668 Py_DECREF(product); 641 Py_DECREF(product);
669 it->start = sum; 642 it->start = sum;
670 if (!it->start) 643 if (!it->start)
671 goto create_failure; 644 goto create_failure;
672 it->step = PyNumber_Negative(range->step); 645 it->step = PyNumber_Negative(range->step);
673 if (!it->step) { 646 if (!it->step) {
674 Py_DECREF(it->start); 647 Py_DECREF(it->start);
675 PyObject_Del(it); 648 PyObject_Del(it);
676 return NULL; 649 return NULL;
677 } 650 }
678 651
679 /* Steal reference to len. */ 652 /* Steal reference to len. */
680 it->len = len; 653 it->length = len;
681 654
682 it->index = PyLong_FromLong(0); 655 it->index = PyLong_FromLong(0);
683 if (!it->index) { 656 if (!it->index) {
684 Py_DECREF(it); 657 Py_DECREF(it);
685 return NULL; 658 return NULL;
686 } 659 }
687 660
688 return (PyObject *)it; 661 return (PyObject *)it;
689 662
690 create_failure: 663 create_failure:
691 Py_XDECREF(len); 664 Py_XDECREF(len);
692 PyObject_Del(it); 665 PyObject_Del(it);
693 return NULL; 666 return NULL;
694 } 667 }
OLDNEW

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld r497