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

Delta Between Two Patch Sets: Objects/rangeobject.c

Issue 602: range: lean and mean (Closed) SVN Base: http://svn.python.org/view/*checkout*/python/branches/py3k/
Left Patch Set: address more concerns Created 4 months, 1 week ago , Downloaded from: http://bugs.python.org/file10183/range_lean_and_mean5.patch
Right Patch Set: in response to reviews Created 4 months, 1 week ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
LEFTRIGHT
1 /* Range object implementation */ 1 /* Range object implementation */
2 2
3 #include "Python.h" 3 #include "Python.h"
4 #include "structmember.h" 4 #include "structmember.h"
5 5
6 /* Support objects whose length is > PY_SSIZE_T_MAX. 6 /* Support objects whose length is > PY_SSIZE_T_MAX.
7 7
8 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.
9 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
10 would presumably help perf. 10 would presumably help perf.
11 */ 11 */
12 12
13 typedef struct { 13 typedef struct {
14 PyObject_HEAD 14 PyObject_HEAD
15 PyObject *start; 15 PyObject *start;
16 PyObject *stop; 16 PyObject *stop;
17 PyObject *step; 17 PyObject *step;
18 PyObject *length; 18 PyObject *length;
19 } rangeobject; 19 } rangeobject;
20 20
21 /* Helper function for validating step. Always returns a new reference or 21 /* Helper function for validating step. Always returns a new reference or
22 NULL on error. 22 NULL on error.
23 */ 23 */
24 static PyObject * 24 static PyObject *
25 validate_step(PyObject *step) 25 validate_step(PyObject *step)
26 { 26 {
27 /* No step specified, use a step of 1. */ 27 /* No step specified, use a step of 1. */
28 if (!step) 28 if (!step)
29 return PyLong_FromLong(1); 29 return PyLong_FromLong(1);
30 30
31 step = PyNumber_Index(step); 31 step = PyNumber_Index(step);
32 if (step) { 32 if (step) {
33 Py_ssize_t istep = PyNumber_AsSsize_t(step, NULL); 33 Py_ssize_t istep = PyNumber_AsSsize_t(step, NULL);
34 if (istep == -1 && PyErr_Occurred()) { 34 if (istep == -1 && PyErr_Occurred()) {
35 /* Ignore OverflowError, we know the value isn't 0. */ 35 /* Ignore OverflowError, we know the value isn't 0. */
36 PyErr_Clear(); 36 PyErr_Clear();
37 } 37 }
38 else if (istep == 0) { 38 else if (istep == 0) {
39 PyErr_SetString(PyExc_ValueError, 39 PyErr_SetString(PyExc_ValueError,
40 "range() arg 3 must not be zero"); 40 "range() arg 3 must not be zero");
41 Py_CLEAR(step); 41 Py_CLEAR(step);
42 } 42 }
43 } 43 }
44 44
45 return step; 45 return step;
46 } 46 }
47 47
48 static PyObject* range_compute_length(PyObject *start, 48 static PyObject* range_compute_length(PyObject *start,
49 PyObject *stop, PyObject *step); 49 PyObject *stop, PyObject *step);
50 50
51 /* 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?
52 range(-10) 52 range(-10)
53 range(0, -5) 53 range(0, -5)
54 range(0, 5, -1) 54 range(0, 5, -1)
55 */ 55 */
56 static PyObject * 56 static PyObject *
57 range_new(PyTypeObject *type, PyObject *args, PyObject *kw) 57 range_new(PyTypeObject *type, PyObject *args, PyObject *kw)
58 { 58 {
59 rangeobject *obj = NULL; 59 rangeobject *obj = NULL;
60 PyObject *start = NULL, *stop = NULL, *step = NULL, *length = NULL; 60 PyObject *start = NULL, *stop = NULL, *step = NULL, *length = NULL;
61 61
62 if (!_PyArg_NoKeywords("range()", kw)) 62 if (!_PyArg_NoKeywords("range()", kw))
63 return NULL; 63 return NULL;
64 64
65 if (PyTuple_Size(args) <= 1) { 65 if (PyTuple_Size(args) <= 1) {
66 if (!PyArg_UnpackTuple(args, "range", 1, 1, &stop)) 66 if (!PyArg_UnpackTuple(args, "range", 1, 1, &stop))
67 goto Fail; 67 goto Fail;
68 stop = PyNumber_Index(stop); 68 stop = PyNumber_Index(stop);
69 if (!stop) 69 if (!stop)
70 goto Fail; 70 goto Fail;
71 start = PyLong_FromLong(0); 71 start = PyLong_FromLong(0);
72 step = PyLong_FromLong(1); 72 step = PyLong_FromLong(1);
73 if (!start || !step) 73 if (!start || !step)
74 goto Fail; 74 goto Fail;
75 } 75 }
76 else { 76 else {
77 if (!PyArg_UnpackTuple(args, "range", 2, 3, 77 if (!PyArg_UnpackTuple(args, "range", 2, 3,
78 &start, &stop, &step)) 78 &start, &stop, &step))
79 goto Fail; 79 goto Fail;
80 80
81 /* Convert borrowed refs to owned refs */ 81 /* Convert borrowed refs to owned refs */
82 start = PyNumber_Index(start); 82 start = PyNumber_Index(start);
83 stop = PyNumber_Index(stop); 83 stop = PyNumber_Index(stop);
84 step = validate_step(step); 84 step = validate_step(step);
85 if (!start || !stop || !step) 85 if (!start || !stop || !step)
86 goto Fail; 86 goto Fail;
87 } 87 }
88 88
89 length = range_compute_length(start, stop, step); 89 length = range_compute_length(start, stop, step);
90 if (length == NULL) 90 if (length == NULL)
91 goto Fail; 91 goto Fail;
92 obj = PyObject_New(rangeobject, &PyRange_Type); 92 obj = PyObject_New(rangeobject, &PyRange_Type);
93 if (obj == NULL) 93 if (obj == NULL)
94 goto Fail; 94 goto Fail;
95 obj->start = start; 95 obj->start = start;
96 obj->stop = stop; 96 obj->stop = stop;
97 obj->step = step; 97 obj->step = step;
98 obj->length = length; 98 obj->length = length;
99 return (PyObject *) obj; 99 return (PyObject *) obj;
100 100
101 Fail: 101 Fail:
102 Py_XDECREF(start); 102 Py_XDECREF(start);
103 Py_XDECREF(stop); 103 Py_XDECREF(stop);
104 Py_XDECREF(step); 104 Py_XDECREF(step);
105 Py_XDECREF(length); 105 Py_XDECREF(length);
106 return NULL; 106 return NULL;
107 } 107 }
108 108
109 PyDoc_STRVAR(range_doc, 109 PyDoc_STRVAR(range_doc,
110 "range([start,] stop[, step]) -> range object\n\ 110 "range([start,] stop[, step]) -> range object\n\
111 \n\ 111 \n\
112 Return an arithmetic progression of numbers from start " 112 Return an arithmetic progression of numbers from start "
113 "to stop (exclusive) by step."); 113 "to stop (exclusive) by step.");
114 114
115 static void 115 static void
116 range_dealloc(rangeobject *r) 116 range_dealloc(rangeobject *r)
117 { 117 {
118 Py_DECREF(r->start); 118 Py_DECREF(r->start);
119 Py_DECREF(r->stop); 119 Py_DECREF(r->stop);
120 Py_DECREF(r->step); 120 Py_DECREF(r->step);
121 Py_DECREF(r->length); 121 Py_DECREF(r->length);
122 PyObject_Del(r); 122 PyObject_Del(r);
123 } 123 }
124 124
GvR 2008/05/03 05:04:35 Hm. I didn't mean for you to delete the entire com
125 /*Return number of items in range (lo, hi, step), when arguments are
126 * PyLong objects. step > 0 required. Return a PyLong with the length.
127 * Return NULL when there is an error.*/
128 static PyObject * 125 static PyObject *
129 range_compute_length(PyObject *start, PyObject *stop, PyObject *step) 126 range_compute_length(PyObject *start, PyObject *stop, PyObject *step)
130 { 127 {
131 /* ------------------------------------------------------------- 128 /* -------------------------------------------------------------
132 Algorithm is equal to that of get_len_of_range(), but it operates 129 Algorithm is equal to that of get_len_of_range(), but it operates
133 on PyObjects (which are assumed to be PyLong or PyInt objects). 130 on PyObjects (which are assumed to be PyLong or PyInt objects).
134 ---------------------------------------------------------------*/ 131 ---------------------------------------------------------------*/
135 int cmp_result, cmp_call; 132 int cmp_result, cmp_call;
136 PyObject *lo, *hi; 133 PyObject *lo, *hi;
137 PyObject *diff = NULL; 134 PyObject *diff = NULL;
138 PyObject *one = NULL; 135 PyObject *one = NULL;
139 PyObject *tmp1 = NULL, *tmp2 = NULL, *result; 136 PyObject *tmp1 = NULL, *tmp2 = NULL, *result;
140 /* holds sub-expression evaluations */ 137 /* holds sub-expression evaluations */
141 138
142 PyObject *zero = PyLong_FromLong(0); 139 PyObject *zero = PyLong_FromLong(0);
143 if (zero == NULL) 140 if (zero == NULL)
144 return NULL; 141 return NULL;
145 cmp_call = PyObject_Cmp(step, zero, &cmp_result); 142 cmp_call = PyObject_Cmp(step, zero, &cmp_result);
146 Py_DECREF(zero); 143 Py_DECREF(zero);
147 if (cmp_call == -1) 144 if (cmp_call == -1)
148 return NULL; 145 return NULL;
149 146
150 assert(cmp_result != 0); 147 assert(cmp_result != 0);
151 if (cmp_result > 0) { 148 if (cmp_result > 0) {
152 lo = start; 149 lo = start;
153 hi = stop; 150 hi = stop;
154 Py_INCREF(step); 151 Py_INCREF(step);
155 } else { 152 } else {
156 lo = stop; 153 lo = stop;
157 hi = start; 154 hi = start;
158 step = PyNumber_Negative(step); 155 step = PyNumber_Negative(step);
159 if (!step) 156 if (!step)
160 goto Fail; 157 goto Fail;
161 } 158 }
162 159
163 /* if (lo >= hi), return length of 0. */ 160 /* if (lo >= hi), return length of 0. */
164 if (PyObject_Compare(lo, hi) >= 0) { 161 if (PyObject_Compare(lo, hi) >= 0) {
165 Py_XDECREF(step); 162 Py_XDECREF(step);
166 return PyLong_FromLong(0); 163 return PyLong_FromLong(0);
167 } 164 }
168 165
169 if ((one = PyLong_FromLong(1L)) == NULL) 166 if ((one = PyLong_FromLong(1L)) == NULL)
170 goto Fail; 167 goto Fail;
171 168
172 if ((tmp1 = PyNumber_Subtract(hi, lo)) == NULL) 169 if ((tmp1 = PyNumber_Subtract(hi, lo)) == NULL)
173 goto Fail; 170 goto Fail;
174 171
175 if ((diff = PyNumber_Subtract(tmp1, one)) == NULL) 172 if ((diff = PyNumber_Subtract(tmp1, one)) == NULL)
176 goto Fail; 173 goto Fail;
177 174
178 if ((tmp2 = PyNumber_FloorDivide(diff, step)) == NULL) 175 if ((tmp2 = PyNumber_FloorDivide(diff, step)) == NULL)
179 goto Fail; 176 goto Fail;
180 177
181 if ((result = PyNumber_Add(tmp2, one)) == NULL) 178 if ((result = PyNumber_Add(tmp2, one)) == NULL)
182 goto Fail; 179 goto Fail;
183 180
184 Py_DECREF(tmp2); 181 Py_DECREF(tmp2);
185 Py_DECREF(diff); 182 Py_DECREF(diff);
186 Py_DECREF(step); 183 Py_DECREF(step);
187 Py_DECREF(tmp1); 184 Py_DECREF(tmp1);
188 Py_DECREF(one); 185 Py_DECREF(one);
189 return result; 186 return result;
190 187
191 Fail: 188 Fail:
192 Py_XDECREF(tmp2); 189 Py_XDECREF(tmp2);
193 Py_XDECREF(diff); 190 Py_XDECREF(diff);
194 Py_XDECREF(step); 191 Py_XDECREF(step);
195 Py_XDECREF(tmp1); 192 Py_XDECREF(tmp1);
196 Py_XDECREF(one); 193 Py_XDECREF(one);
197 return NULL; 194 return NULL;
198 } 195 }
199 196
200 static Py_ssize_t 197 static PyObject *
201 range_length(rangeobject *r) 198 range_length_hint(rangeobject *r)
202 { 199 {
203 return PyLong_AsSsize_t(r->length); 200 Py_INCREF(r->length);
204 } 201 return r->length;
202 }
203
204 PyDoc_STRVAR(range_length_hint_doc,
205 "__length_hint__() -> int\n"
206 "Return a estimate of len(list(range)).");
205 207
206 208
207 static PyObject * 209 static PyObject *
208 range_repr(rangeobject *r) 210 range_repr(rangeobject *r)
209 { 211 {
210 Py_ssize_t istep; 212 Py_ssize_t istep;
211 213
212 /* Check for special case values for printing. We don't always 214 /* Check for special case values for printing. We don't always
213 need the step value. We don't care about errors 215 need the step value. We don't care about errors
214 (it means overflow), so clear the errors. */ 216 (it means overflow), so clear the errors. */
215 istep = PyNumber_AsSsize_t(r->step, NULL); 217 istep = PyNumber_AsSsize_t(r->step, NULL);
216 if (istep != 1 || (istep == -1 && PyErr_Occurred())) { 218 if (istep != 1 || (istep == -1 && PyErr_Occurred())) {
217 PyErr_Clear(); 219 PyErr_Clear();
218 } 220 }
219 221
220 if (istep == 1) 222 if (istep == 1)
221 return PyUnicode_FromFormat("range(%R, %R)", r->start, r->stop); 223 return PyUnicode_FromFormat("range(%R, %R)", r->start, r->stop);
222 else 224 else
223 return PyUnicode_FromFormat("range(%R, %R, %R)", 225 return PyUnicode_FromFormat("range(%R, %R, %R)",
224 r->start, r->stop, r->step); 226 r->start, r->stop, r->step);
225 } 227 }
226 228
227 static PyMemberDef range_members[] = { 229 static PyMemberDef range_members[] = {
228 {"start", T_OBJECT, offsetof(rangeobject, start), READONLY}, 230 {"start", T_OBJECT, offsetof(rangeobject, start), READONLY},
229 {"stop", T_OBJECT, offsetof(rangeobject, stop), READONLY}, 231 {"stop", T_OBJECT, offsetof(rangeobject, stop), READONLY},
230 {"step", T_OBJECT, offsetof(rangeobject, step), READONLY}, 232 {"step", T_OBJECT, offsetof(rangeobject, step), READONLY},
231 {0} 233 {0}
232 }; 234 };
233 235
234 static PyObject * range_iter(PyObject *seq); 236 static PyObject * range_iter(PyObject *seq);
235 static PyObject * range_reverse(PyObject *seq); 237 static PyObject * range_reverse(PyObject *seq);
236 238
237 PyDoc_STRVAR(reverse_doc, 239 PyDoc_STRVAR(reverse_doc,
238 "Returns a reverse iterator."); 240 "Returns a reverse iterator.");
239 241
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 };
252
253 static PyMethodDef range_methods[] = { 242 static PyMethodDef range_methods[] = {
254 {"__reversed__", (PyCFunction)range_reverse, METH_NOARGS, 243 {"__reversed__", (PyCFunction)range_reverse, METH_NOARGS,
255 reverse_doc}, 244 reverse_doc},
245 {"__length_hint__", (PyCFunction)range_length_hint, METH_NOARGS,
246 range_length_hint_doc},
256 {NULL, NULL} /* sentinel */ 247 {NULL, NULL} /* sentinel */
257 }; 248 };
258 249
259 PyTypeObject PyRange_Type = { 250 PyTypeObject PyRange_Type = {
260 PyVarObject_HEAD_INIT(&PyType_Type, 0) 251 PyVarObject_HEAD_INIT(&PyType_Type, 0)
261 "range", /* Name of this type */ 252 "range", /* Name of this type */
262 sizeof(rangeobject), /* Basic object size */ 253 sizeof(rangeobject), /* Basic object size */
263 0, /* Item size for varobject */ 254 0, /* Item size for varobject */
264 (destructor)range_dealloc, /* tp_dealloc */ 255 (destructor)range_dealloc, /* tp_dealloc */
265 0, /* tp_print */ 256 0, /* tp_print */
266 0, /* tp_getattr */ 257 0, /* tp_getattr */
267 0, /* tp_setattr */ 258 0, /* tp_setattr */
268 0, /* tp_compare */ 259 0, /* tp_compare */
269 (reprfunc)range_repr, /* tp_repr */ 260 (reprfunc)range_repr, /* tp_repr */
270 0, /* tp_as_number */ 261 0, /* tp_as_number */
271 &range_as_sequence, /* tp_as_sequence */ 262 0, /* tp_as_sequence */
272 0, /* tp_as_mapping */ 263 0, /* tp_as_mapping */
273 0, /* tp_hash */ 264 0, /* tp_hash */
274 0, /* tp_call */ 265 0, /* tp_call */
275 0, /* tp_str */ 266 0, /* tp_str */
276 PyObject_GenericGetAttr, /* tp_getattro */ 267 PyObject_GenericGetAttr, /* tp_getattro */
277 0, /* tp_setattro */ 268 0, /* tp_setattro */
278 0, /* tp_as_buffer */ 269 0, /* tp_as_buffer */
279 Py_TPFLAGS_DEFAULT, /* tp_flags */ 270 Py_TPFLAGS_DEFAULT, /* tp_flags */
280 range_doc, /* tp_doc */ 271 range_doc, /* tp_doc */
281 0, /* tp_traverse */ 272 0, /* tp_traverse */
282 0, /* tp_clear */ 273 0, /* tp_clear */
283 0, /* tp_richcompare */ 274 0, /* tp_richcompare */
284 0, /* tp_weaklistoffset */ 275 0, /* tp_weaklistoffset */
285 range_iter, /* tp_iter */ 276 range_iter, /* tp_iter */
286 0, /* tp_iternext */ 277 0, /* tp_iternext */
287 range_methods, /* tp_methods */ 278 range_methods, /* tp_methods */
288 range_members, /* tp_members */ 279 range_members, /* tp_members */
289 0, /* tp_getset */ 280 0, /* tp_getset */
290 0, /* tp_base */ 281 0, /* tp_base */
291 0, /* tp_dict */ 282 0, /* tp_dict */
292 0, /* tp_descr_get */ 283 0, /* tp_descr_get */
293 0, /* tp_descr_set */ 284 0, /* tp_descr_set */
294 0, /* tp_dictoffset */ 285 0, /* tp_dictoffset */
295 0, /* tp_init */ 286 0, /* tp_init */
296 0, /* tp_alloc */ 287 0, /* tp_alloc */
297 range_new, /* tp_new */ 288 range_new, /* tp_new */
298 }; 289 };
299 290
300 /*********************** range Iterator **************************/ 291 /*********************** range Iterator **************************/
301 292
302 /* There are 2 types of iterators, one for C longs, the other for 293 /* There are 2 types of iterators, one for C longs, the other for
303 Python longs (ie, PyObjects). This should make iteration fast 294 Python longs (ie, PyObjects). This should make iteration fast
304 in the normal case, but possible for any numeric value. 295 in the normal case, but possible for any numeric value.
305 */ 296 */
306 297
307 typedef struct { 298 typedef struct {
308 PyObject_HEAD 299 PyObject_HEAD
309 long index; 300 long index;
310 long start; 301 long start;
311 long step; 302 long step;
312 long len; 303 long len;
313 } rangeiterobject; 304 } rangeiterobject;
314 305
315 static PyObject * 306 static PyObject *
316 rangeiter_next(rangeiterobject *r) 307 rangeiter_next(rangeiterobject *r)
317 { 308 {
318 if (r->index < r->len) 309 if (r->index < r->len)
319 return PyLong_FromLong(r->start + (r->index++) * r->step); 310 return PyLong_FromLong(r->start + (r->index++) * r->step);
320 return NULL; 311 return NULL;
321 } 312 }
(...skipping 203 matching lines...) Show 10 above Show 10 below
525 0, /* tp_setattro */ 516 0, /* tp_setattro */
526 0, /* tp_as_buffer */ 517 0, /* tp_as_buffer */
527 Py_TPFLAGS_DEFAULT, /* tp_flags */ 518 Py_TPFLAGS_DEFAULT, /* tp_flags */
528 0, /* tp_doc */ 519 0, /* tp_doc */
529 0, /* tp_traverse */ 520 0, /* tp_traverse */
530 0, /* tp_clear */ 521 0, /* tp_clear */
531 0, /* tp_richcompare */ 522 0, /* tp_richcompare */
532 0, /* tp_weaklistoffset */ 523 0, /* tp_weaklistoffset */
533 PyObject_SelfIter, /* tp_iter */ 524 PyObject_SelfIter, /* tp_iter */
534 (iternextfunc)longrangeiter_next, /* tp_iternext */ 525 (iternextfunc)longrangeiter_next, /* tp_iternext */
535 longrangeiter_methods, /* tp_methods */ 526 longrangeiter_methods, /* tp_methods */
536 0, 527 0,
537 }; 528 };
538 529
539 static PyObject * 530 static PyObject *
540 range_iter(PyObject *seq) 531 range_iter(PyObject *seq)
541 { 532 {
542 rangeobject *r = (rangeobject *)seq; 533 rangeobject *r = (rangeobject *)seq;
543 longrangeiterobject *it; 534 longrangeiterobject *it;
544 long lstart, lstop, lstep; 535 long lstart, lstop, lstep;
545 536
546 assert(PyRange_Check(seq)); 537 assert(PyRange_Check(seq));
547 538
548 /* If all three fields convert to long, use the int version */ 539 /* If all three fields convert to long, use the int version */
549 lstart = PyLong_AsLong(r->start); 540 lstart = PyLong_AsLong(r->start);
550 if (lstart != -1 || !PyErr_Occurred()) { 541 if (lstart != -1 || !PyErr_Occurred()) {
551 lstop = PyLong_AsLong(r->stop); 542 lstop = PyLong_AsLong(r->stop);
552 if (lstop != -1 || !PyErr_Occurred()) { 543 if (lstop != -1 || !PyErr_Occurred()) {
553 lstep = PyLong_AsLong(r->step); 544 lstep = PyLong_AsLong(r->step);
554 if (lstep != -1 || !PyErr_Occurred()) 545 if (lstep != -1 || !PyErr_Occurred())
555 return int_range_iter(lstart, lstop, lstep); 546 return int_range_iter(lstart, lstop, lstep);
556 } 547 }
557 } 548 }
558 /* Some conversion failed, so there is an error set. Clear it, 549 /* Some conversion failed, so there is an error set. Clear it,
559 and try again with a long range. */ 550 and try again with a long range. */
560 PyErr_Clear(); 551 PyErr_Clear();
561 552
562 it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type); 553 it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type);
563 if (it == NULL) 554 if (it == NULL)
564 return NULL; 555 return NULL;
565 556
566 /* Do all initialization here, so we can DECREF on failure. */ 557 /* Do all initialization here, so we can DECREF on failure. */
567 it->start = r->start; 558 it->start = r->start;
568 it->step = r->step; 559 it->step = r->step;
569 Py_INCREF(it->start); 560 Py_INCREF(it->start);
570 Py_INCREF(it->step); 561 Py_INCREF(it->step);
571 562
572 Py_INCREF(r->length); 563 Py_INCREF(r->length);
573 it->length = r->length; 564 it->length = r->length;
574 it->index = PyLong_FromLong(0); 565 it->index = PyLong_FromLong(0);
575 if (it->index == NULL) 566 if (!it->index)
576 goto create_failure; 567 goto create_failure;
577 568
578 return (PyObject *)it; 569 return (PyObject *)it;
579 570
580 create_failure: 571 create_failure:
581 Py_DECREF(it); 572 Py_DECREF(it);
582 return NULL; 573 return NULL;
583 } 574 }
584 575
585 static PyObject * 576 static PyObject *
586 range_reverse(PyObject *seq) 577 range_reverse(PyObject *seq)
587 { 578 {
588 rangeobject *range = (rangeobject*) seq; 579 rangeobject *range = (rangeobject*) seq;
589 longrangeiterobject *it; 580 longrangeiterobject *it;
590 PyObject *one, *sum, *diff, *len = NULL, *product; 581 PyObject *one, *sum, *diff, *len = NULL, *product;
591 long lstart, lstop, lstep; 582 long lstart, lstop, lstep;
592 583
593 /* XXX(nnorwitz): do the calc for the new start/stop first, 584 /* XXX(nnorwitz): do the calc for the new start/stop first,
594 then if they fit, call the proper iter()? 585 then if they fit, call the proper iter()?
595 */ 586 */
596 assert(PyRange_Check(seq)); 587 assert(PyRange_Check(seq));
597 588
598 /* If all three fields convert to long, use the int version */ 589 /* If all three fields convert to long, use the int version */
599 lstart = PyLong_AsLong(range->start); 590 lstart = PyLong_AsLong(range->start);
600 if (lstart != -1 || !PyErr_Occurred()) { 591 if (lstart != -1 || !PyErr_Occurred()) {
601 lstop = PyLong_AsLong(range->stop); 592 lstop = PyLong_AsLong(range->stop);
602 if (lstop != -1 || !PyErr_Occurred()) { 593 if (lstop != -1 || !PyErr_Occurred()) {
603 lstep = PyLong_AsLong(range->step); 594 lstep = PyLong_AsLong(range->step);
604 if (lstep != -1 || !PyErr_Occurred()) { 595 if (lstep != -1 || !PyErr_Occurred()) {
605 /* XXX(nnorwitz): need to check for overflow and simplify. */ 596 /* XXX(nnorwitz): need to check for overflow and simplify. */
606 long len = get_len_of_range(lstart, lstop, lstep); 597 long len = get_len_of_range(lstart, lstop, lstep);
607 long new_start = lstart + (len - 1) * lstep; 598 long new_start = lstart + (len - 1) * lstep;
608 long new_stop = lstart; 599 long new_stop = lstart;
609 if (lstep > 0) 600 if (lstep > 0)
610 new_stop -= 1; 601 new_stop -= 1;
611 else 602 else
612 new_stop += 1; 603 new_stop += 1;
613 return int_range_iter(new_start, new_stop, -lstep); 604 return int_range_iter(new_start, new_stop, -lstep);
614 } 605 }
615 } 606 }
616 } 607 }
617 PyErr_Clear(); 608 PyErr_Clear();
618 609
619 it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type); 610 it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type);
620 if (it == NULL) 611 if (it == NULL)
621 return NULL; 612 return NULL;
622 613
623 /* start + (len - 1) * step */ 614 /* start + (len - 1) * step */
624 Py_INCREF(range->length); 615 Py_INCREF(range->length);
625 len = range->length; 616 len = range->length;
626 617
627 one = PyLong_FromLong(1); 618 one = PyLong_FromLong(1);
628 if (!one) 619 if (!one)
629 goto create_failure; 620 goto create_failure;
630 621
631 diff = PyNumber_Subtract(len, one); 622 diff = PyNumber_Subtract(len, one);
632 Py_DECREF(one); 623 Py_DECREF(one);
633 if (!diff) 624 if (!diff)
634 goto create_failure; 625 goto create_failure;
635 626
636 product = PyNumber_Multiply(len, range->step); 627 product = PyNumber_Multiply(len, range->step);
637 if (!product) 628 if (!product)
638 goto create_failure; 629 goto create_failure;
639 630
640 sum = PyNumber_Add(range->start, product); 631 sum = PyNumber_Add(range->start, product);
641 Py_DECREF(product); 632 Py_DECREF(product);
642 it->start = sum; 633 it->start = sum;
643 if (!it->start) 634 if (!it->start)
644 goto create_failure; 635 goto create_failure;
645 it->step = PyNumber_Negative(range->step); 636 it->step = PyNumber_Negative(range->step);
646 if (!it->step) { 637 if (!it->step) {
647 Py_DECREF(it->start); 638 Py_DECREF(it->start);
648 PyObject_Del(it); 639 PyObject_Del(it);
649 return NULL; 640 return NULL;
650 } 641 }
651 642
652 /* Steal reference to len. */ 643 /* Steal reference to len. */
653 it->length = len; 644 it->length = len;
654