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

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: use PyMemberDef Created 4 months, 1 week ago , Downloaded from: http://bugs.python.org/file10155/range_lean_and_mean2.patch
Right Patch Set: Created 4 months, 1 week ago , Downloaded from: http://bugs.python.org/file10152/range_lean_and_mean.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:
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"
5 4
6 /* Support objects whose length is > PY_SSIZE_T_MAX. 5 /* Support objects whose length is > PY_SSIZE_T_MAX.
7 6
8 This could be sped up for small PyLongs if they fit in an Py_ssize_t. 7 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 8 This only matters on Win64. Though we could use PY_LONG_LONG which
10 would presumably help perf. 9 would presumably help perf.
11 */ 10 */
12 11
13 typedef struct { 12 typedef struct {
14 PyObject_HEAD 13 PyObject_HEAD
15 PyObject *start; 14 PyObject *start;
16 PyObject *stop; 15 PyObject *stop;
17 PyObject *step; 16 PyObject *step;
18 PyObject *length; 17 PyObject *length;
mvloewis 2008/05/02 05:43:57 What is the purpose of caching the length in the r
GvR 2008/05/02 13:52:47 On 2008/05/02 05:43:57, mvloewis wrote: > What is
Benjamin 2008/05/02 16:56:18 On 2008/05/02 05:43:57, mvloewis wrote: > What is
19 } rangeobject; 18 } rangeobject;
20 19
21 /* Helper function for validating step. Always returns a new reference or 20 /* Helper function for validating step. Always returns a new reference or
22 NULL on error. 21 NULL on error.
23 */ 22 */
24 static PyObject * 23 static PyObject *
25 validate_step(PyObject *step) 24 validate_step(PyObject *step)
26 { 25 {
27 /* No step specified, use a step of 1. */ 26 /* No step specified, use a step of 1. */
28 if (!step) 27 if (!step)
29 return PyLong_FromLong(1); 28 return PyLong_FromLong(1);
30 29
31 step = PyNumber_Index(step); 30 step = PyNumber_Index(step);
32 if (step) { 31 if (step) {
33 Py_ssize_t istep = PyNumber_AsSsize_t(step, NULL); 32 Py_ssize_t istep = PyNumber_AsSsize_t(step, NULL);
34 if (istep == -1 && PyErr_Occurred()) { 33 if (istep == -1 && PyErr_Occurred()) {
35 /* Ignore OverflowError, we know the value isn't 0. */ 34 /* Ignore OverflowError, we know the value isn't 0. */
36 PyErr_Clear(); 35 PyErr_Clear();
37 } 36 }
38 else if (istep == 0) { 37 else if (istep == 0) {
39 PyErr_SetString(PyExc_ValueError, 38 PyErr_SetString(PyExc_ValueError,
40 "range() arg 3 must not be zero"); 39 "range() arg 3 must not be zero");
41 Py_CLEAR(step); 40 Py_CLEAR(step);
42 } 41 }
43 } 42 }
44 43
45 return step; 44 return step;
46 } 45 }
47 46
48 static PyObject* range_compute_length(PyObject *start, 47 static PyObject* range_compute_length(PyObject *start,
49 PyObject *stop, PyObject *step); 48 PyObject *stop, PyObject *step);
GvR 2008/05/02 13:52:47 This line is indented one space too many.
50 49
51 /* XXX(nnorwitz): should we error check if the user passes any empty ranges? 50 /* XXX(nnorwitz): should we error check if the user passes any empty ranges?
52 range(-10) 51 range(-10)
53 range(0, -5) 52 range(0, -5)
54 range(0, 5, -1) 53 range(0, 5, -1)
55 */ 54 */
56 static PyObject * 55 static PyObject *
57 range_new(PyTypeObject *type, PyObject *args, PyObject *kw) 56 range_new(PyTypeObject *type, PyObject *args, PyObject *kw)
58 { 57 {
59 rangeobject *obj = NULL; 58 rangeobject *obj = NULL;
60 PyObject *start = NULL, *stop = NULL, *step = NULL, *length = NULL; 59 PyObject *start = NULL, *stop = NULL, *step = NULL, *length = NULL;
61 60
62 if (!_PyArg_NoKeywords("range()", kw)) 61 if (!_PyArg_NoKeywords("range()", kw))
63 return NULL; 62 return NULL;
64 63
65 if (PyTuple_Size(args) <= 1) { 64 if (PyTuple_Size(args) <= 1) {
66 if (!PyArg_UnpackTuple(args, "range", 1, 1, &stop)) 65 if (!PyArg_UnpackTuple(args, "range", 1, 1, &stop))
67 goto Fail; 66 goto Fail;
68 stop = PyNumber_Index(stop); 67 stop = PyNumber_Index(stop);
69 if (!stop) 68 if (!stop)
70 goto Fail; 69 goto Fail;
71 start = PyLong_FromLong(0); 70 start = PyLong_FromLong(0);
72 step = PyLong_FromLong(1); 71 step = PyLong_FromLong(1);
73 if (!start || !step) 72 if (!start || !step)
74 goto Fail; 73 goto Fail;
75 } 74 }
76 else { 75 else {
77 if (!PyArg_UnpackTuple(args, "range", 2, 3, 76 if (!PyArg_UnpackTuple(args, "range", 2, 3,
78 &start, &stop, &step)) 77 &start, &stop, &step))
79 goto Fail; 78 goto Fail;
80 79
81 /* Convert borrowed refs to owned refs */ 80 /* Convert borrowed refs to owned refs */
82 start = PyNumber_Index(start); 81 start = PyNumber_Index(start);
83 stop = PyNumber_Index(stop); 82 stop = PyNumber_Index(stop);
84 step = validate_step(step); 83 step = validate_step(step);
85 if (!start || !stop || !step) 84 if (!start || !stop || !step)
86 goto Fail; 85 goto Fail;
87 } 86 }
88 87
89 length = range_compute_length(start, stop, step); 88 length = range_compute_length(start, stop, step);
90 if (length == NULL) 89 if (length == NULL)
91 goto Fail; 90 goto Fail;
92 obj = PyObject_New(rangeobject, &PyRange_Type); 91 obj = PyObject_New(rangeobject, &PyRange_Type);
93 if (obj == NULL) 92 if (obj == NULL)
94 goto Fail; 93 goto Fail;
95 obj->start = start; 94 obj->start = start;
96 obj->stop = stop; 95 obj->stop = stop;
97 obj->step = step; 96 obj->step = step;
98 obj->length = length; 97 obj->length = length;
99 return (PyObject *) obj; 98 return (PyObject *) obj;
100 99
101 Fail: 100 Fail:
102 Py_XDECREF(start); 101 Py_XDECREF(start);
103 Py_XDECREF(stop); 102 Py_XDECREF(stop);
104 Py_XDECREF(step); 103 Py_XDECREF(step);
105 Py_XDECREF(length); 104 Py_XDECREF(length);
106 return NULL; 105 return NULL;
107 } 106 }
108 107
109 PyDoc_STRVAR(range_doc, 108 PyDoc_STRVAR(range_doc,
110 "range([start,] stop[, step]) -> range object\n\ 109 "range([start,] stop[, step]) -> range object\n\
111 \n\ 110 \n\
112 Returns a virtual sequence of numbers from start to stop by step."); 111 Returns a virtual sequence of numbers from start to stop by step.");
GvR 2008/05/02 13:52:47 I really don't want to use the word sequence here.
113 112
114 static void 113 static void
115 range_dealloc(rangeobject *r) 114 range_dealloc(rangeobject *r)
116 { 115 {
117 Py_DECREF(r->start); 116 Py_DECREF(r->start);
118 Py_DECREF(r->stop); 117 Py_DECREF(r->stop);
119 Py_DECREF(r->step); 118 Py_DECREF(r->step);
120 Py_DECREF(r->length); 119 Py_DECREF(r->length);
121 PyObject_Del(r); 120 PyObject_Del(r);
122 } 121 }
123 122
124 /* Return number of items in range (lo, hi, step), when arguments are 123 /* Return number of items in range (lo, hi, step), when arguments are
125 * PyInt or PyLong objects. step > 0 required. Return a value < 0 if 124 * PyInt or PyLong objects. step > 0 required. Return a value < 0 if
126 * & only if the true value is too large to fit in a signed long. 125 * & only if the true value is too large to fit in a signed long.
127 * Arguments MUST return 1 with either PyLong_Check() or 126 * Arguments MUST return 1 with either PyLong_Check() or
128 * PyLong_Check(). Return -1 when there is an error. 127 * PyLong_Check(). Return -1 when there is an error.
GvR 2008/05/02 13:52:47 Not your fault, but this comment still references
129 */ 128 */
130 static PyObject * 129 static PyObject *
131 range_compute_length(PyObject *start, PyObject *stop, PyObject *step) 130 range_compute_length(PyObject *start, PyObject *stop, PyObject *step)
132 { 131 {
133 /* ------------------------------------------------------------- 132 /* -------------------------------------------------------------
134 Algorithm is equal to that of get_len_of_range(), but it operates 133 Algorithm is equal to that of get_len_of_range(), but it operates
135 on PyObjects (which are assumed to be PyLong or PyInt objects). 134 on PyObjects (which are assumed to be PyLong or PyInt objects).
136 ---------------------------------------------------------------*/ 135 ---------------------------------------------------------------*/
137 int cmp_result, cmp_call; 136 int cmp_result, cmp_call;
138 PyObject *lo, *hi; 137 PyObject *lo, *hi;
139 PyObject *diff = NULL; 138 PyObject *diff = NULL;
140 PyObject *one = NULL; 139 PyObject *one = NULL;
141 PyObject *tmp1 = NULL, *tmp2 = NULL, *result; 140 PyObject *tmp1 = NULL, *tmp2 = NULL, *result;
142 /* holds sub-expression evaluations */ 141 /* holds sub-expression evaluations */
143 142
144 PyObject *zero = PyLong_FromLong(0); 143 PyObject *zero = PyLong_FromLong(0);
145 if (zero == NULL) 144 if (zero == NULL)
146 return NULL; 145 return NULL;
147 cmp_call = PyObject_Cmp(step, zero, &cmp_result); 146 cmp_call = PyObject_Cmp(step, zero, &cmp_result);
148 Py_DECREF(zero); 147 Py_DECREF(zero);
149 if (cmp_call == -1) 148 if (cmp_call == -1)
150 return NULL; 149 return NULL;
151 150
152 assert(cmp_result != 0); 151 assert(cmp_result != 0);
153 if (cmp_result > 0) { 152 if (cmp_result > 0) {
154 lo = start; 153 lo = start;
155 hi = stop; 154 hi = stop;
156 Py_INCREF(step); 155 Py_INCREF(step);
157 } else { 156 } else {
158 lo = stop; 157 lo = stop;
159 hi = start; 158 hi = start;
160 step = PyNumber_Negative(step); 159 step = PyNumber_Negative(step);
161 if (!step) 160 if (!step)
162 goto Fail; 161 goto Fail;
163 } 162 }
164 163
165 /* if (lo >= hi), return length of 0. */ 164 /* if (lo >= hi), return length of 0. */
166 if (PyObject_Compare(lo, hi) >= 0) { 165 if (PyObject_Compare(lo, hi) >= 0) {
167 Py_XDECREF(step); 166 Py_XDECREF(step);
168 return PyLong_FromLong(0); 167 return PyLong_FromLong(0);
169 } 168 }
170 169
171 if ((one = PyLong_FromLong(1L)) == NULL) 170 if ((one = PyLong_FromLong(1L)) == NULL)
172 goto Fail; 171 goto Fail;
173 172
174 if ((tmp1 = PyNumber_Subtract(hi, lo)) == NULL) 173 if ((tmp1 = PyNumber_Subtract(hi, lo)) == NULL)
175 goto Fail; 174 goto Fail;
176 175
177 if ((diff = PyNumber_Subtract(tmp1, one)) == NULL) 176 if ((diff = PyNumber_Subtract(tmp1, one)) == NULL)
178 goto Fail; 177 goto Fail;
179 178
180 if ((tmp2 = PyNumber_FloorDivide(diff, step)) == NULL) 179 if ((tmp2 = PyNumber_FloorDivide(diff, step)) == NULL)
181 goto Fail; 180 goto Fail;
182 181
183 if ((result = PyNumber_Add(tmp2, one)) == NULL) 182 if ((result = PyNumber_Add(tmp2, one)) == NULL)
184 goto Fail; 183 goto Fail;
185 184
186 Py_DECREF(tmp2); 185 Py_DECREF(tmp2);
187 Py_DECREF(diff); 186 Py_DECREF(diff);
188 Py_DECREF(step); 187 Py_DECREF(step);
189 Py_DECREF(tmp1); 188 Py_DECREF(tmp1);
190 Py_DECREF(one); 189 Py_DECREF(one);
191 return result; 190 return result;
192 191
193 Fail: 192 Fail:
194 Py_XDECREF(tmp2); 193 Py_XDECREF(tmp2);
195 Py_XDECREF(diff); 194 Py_XDECREF(diff);
196 Py_XDECREF(step); 195 Py_XDECREF(step);
197 Py_XDECREF(tmp1); 196 Py_XDECREF(tmp1);
198 Py_XDECREF(one); 197 Py_XDECREF(one);
199 return NULL; 198 return NULL;
200 } 199 }
201 200
202 static Py_ssize_t 201 static Py_ssize_t
203 range_length(rangeobject *r) 202 range_length(rangeobject *r)
204 { 203 {
205 return PyLong_AsSsize_t(r->length); 204 return PyLong_AsSsize_t(r->length);
206 } 205 }
207 206
208 207
209 static PyObject * 208 static PyObject *
210 range_repr(rangeobject *r) 209 range_repr(rangeobject *r)
211 { 210 {
212 Py_ssize_t istep; 211 Py_ssize_t istep;
213 212
214 /* Check for special case values for printing. We don't always 213 /* Check for special case values for printing. We don't always
215 need the step value. We don't care about errors 214 need the step value. We don't care about errors
216 (it means overflow), so clear the errors. */ 215 (it means overflow), so clear the errors. */
217 istep = PyNumber_AsSsize_t(r->step, NULL); 216 istep = PyNumber_AsSsize_t(r->step, NULL);
218 if (istep != 1 || (istep == -1 && PyErr_Occurred())) { 217 if (istep != 1 || (istep == -1 && PyErr_Occurred())) {
219 PyErr_Clear(); 218 PyErr_Clear();
220 } 219 }
221 220
222 if (istep == 1) 221 if (istep == 1)
223 return PyUnicode_FromFormat("range(%R, %R)", r->start, r->stop); 222 return PyUnicode_FromFormat("range(%R, %R)", r->start, r->stop);
224 else 223 else
225 return PyUnicode_FromFormat("range(%R, %R, %R)", 224 return PyUnicode_FromFormat("range(%R, %R, %R)",
226 r->start, r->stop, r->step); 225 r->start, r->stop, r->step);
227 } 226 }
228 227
229 static PyMemberDef range_members[] = { 228 static PyObject *
230 {"start", T_OBJECT, offsetof(rangeobject, start), READONLY}, 229 range_getstart(rangeobject *obj)
231 {"stop", T_OBJECT, offsetof(rangeobject, stop), READONLY}, 230 {
232 {"step", T_OBJECT, offsetof(rangeobject, step), READONLY}, 231 return obj->start;
233 {0} 232 }
233
234 static PyObject *
235 range_getstop(rangeobject *obj)
236 {
237 return obj->stop;
238 }
239
240 static PyObject *
241 range_getstep(rangeobject *obj)
242 {
243 return obj->step;
244 }
245
246 static PyGetSetDef range_getset[] = {
247 {"start", (getter)range_getstart, NULL, "The start of the range"},
248 {"stop", (getter)range_getstop, NULL, "Where the range stops."},
249 {"step", (getter)range_getstep, NULL, "How much the range jumps."},
250 {0},
234 }; 251 };
235 252
236 static PySequenceMethods range_as_sequence = { 253 static PySequenceMethods range_as_sequence = {
237 (lenfunc)range_length, /* sq_length */ 254 (lenfunc)range_length, /* sq_length */
GvR 2008/05/02 13:52:47 The latest discussion on the list suggests to remo
238 0, /* sq_concat */ 255 0, /* sq_concat */
239 0, /* sq_repeat */ 256 0, /* sq_repeat */
240 0, /* sq_item */ 257 0, /* sq_item */
241 0, /* sq_slice */ 258 0, /* sq_slice */
242 0, /* sq_ass_item */ 259 0, /* sq_ass_item */
243 0, /* sq_ass_slice */ 260 0, /* sq_ass_slice */
244 0, /* sq_contains */ 261 0, /* sq_contains */
245 }; 262 };
246 263
247 static PyObject * range_iter(PyObject *seq); 264 static PyObject * range_iter(PyObject *seq);
248 static PyObject * range_reverse(PyObject *seq); 265 static PyObject * range_reverse(PyObject *seq);
249 266
250 PyDoc_STRVAR(reverse_doc, 267 PyDoc_STRVAR(reverse_doc,
251 "Returns a reverse iterator."); 268 "Returns a reverse iterator.");
252 269
253 static PyMethodDef range_methods[] = { 270 static PyMethodDef range_methods[] = {
254 {"__reversed__", (PyCFunction)range_reverse, METH_NOARGS, 271 {"__reversed__", (PyCFunction)range_reverse, METH_NOARGS,
255 reverse_doc}, 272 reverse_doc},
256 {NULL, NULL} /* sentinel */ 273 {NULL, NULL} /* sentinel */
257 }; 274 };
258 275
259 PyTypeObject PyRange_Type = { 276 PyTypeObject PyRange_Type = {
260 PyVarObject_HEAD_INIT(&PyType_Type, 0) 277 PyVarObject_HEAD_INIT(&PyType_Type, 0)
261 "range", /* Name of this type */ 278 "range", /* Name of this type */
262 sizeof(rangeobject), /* Basic object size */ 279 sizeof(rangeobject), /* Basic object size */
263 0, /* Item size for varobject */ 280 0, /* Item size for varobject */
264 (destructor)range_dealloc, /* tp_dealloc */ 281 (destructor)range_dealloc, /* tp_dealloc */
265 0, /* tp_print */ 282 0, /* tp_print */
266 0, /* tp_getattr */ 283 0, /* tp_getattr */
267 0, /* tp_setattr */ 284 0, /* tp_setattr */
268 0, /* tp_compare */ 285 0, /* tp_compare */
269 (reprfunc)range_repr, /* tp_repr */ 286 (reprfunc)range_repr, /* tp_repr */
270 0, /* tp_as_number */ 287 0, /* tp_as_number */
271 &range_as_sequence, /* tp_as_sequence */ 288 &range_as_sequence, /* tp_as_sequence */
272 0, /* tp_as_mapping */ 289 0, /* tp_as_mapping */
273 0, /* tp_hash */ 290 0, /* tp_hash */
274 0, /* tp_call */ 291 0, /* tp_call */
275 0, /* tp_str */ 292 0, /* tp_str */
276 PyObject_GenericGetAttr, /* tp_getattro */ 293 PyObject_GenericGetAttr, /* tp_getattro */
277 0, /* tp_setattro */ 294 0, /* tp_setattro */
278 0, /* tp_as_buffer */ 295 0, /* tp_as_buffer */
279 Py_TPFLAGS_DEFAULT, /* tp_flags */ 296 Py_TPFLAGS_DEFAULT, /* tp_flags */
280 range_doc, /* tp_doc */ 297 range_doc, /* tp_doc */
281 0, /* tp_traverse */ 298 0, /* tp_traverse */
282 0, /* tp_clear */ 299 0, /* tp_clear */
283 0, /* tp_richcompare */ 300 0, /* tp_richcompare */
284 0, /* tp_weaklistoffset */ 301 0, /* tp_weaklistoffset */
285 range_iter, /* tp_iter */ 302 range_iter, /* tp_iter */
286 0, /* tp_iternext */ 303 0, /* tp_iternext */
287 range_methods, /* tp_methods */ 304 range_methods, /* tp_methods */
288 range_members,»»/* tp_members */ 305 0, »»/* tp_members */
mvloewis 2008/05/02 20:17:20 Carrying forward from the previous patch set: this
289 0, /* tp_getset */ 306 range_getset,» /* tp_getset */
GvR 2008/05/02 13:52:47 Please use spaces to indent the comment.
290 0, /* tp_base */ 307 0, /* tp_base */
291 0, /* tp_dict */ 308 0, /* tp_dict */
292 0, /* tp_descr_get */ 309 0, /* tp_descr_get */
293 0, /* tp_descr_set */ 310 0, /* tp_descr_set */
294 0, /* tp_dictoffset */ 311 0, /* tp_dictoffset */
295 0, /* tp_init */ 312 0, /* tp_init */
296 0, /* tp_alloc */ 313 0, /* tp_alloc */
297 range_new, /* tp_new */ 314 range_new, /* tp_new */
298 }; 315 };
299 316
300 /*********************** range Iterator **************************/ 317 /*********************** range Iterator **************************/
301 318
302 /* There are 2 types of iterators, one for C longs, the other for 319 /* There are 2 types of iterators, one for C longs, the other for
303 Python longs (ie, PyObjects). This should make iteration fast 320 Python longs (ie, PyObjects). This should make iteration fast
304 in the normal case, but possible for any numeric value. 321 in the normal case, but possible for any numeric value.
305 */ 322 */
306 323
307 typedef struct { 324 typedef struct {
308 PyObject_HEAD 325 PyObject_HEAD
309 long index; 326 long index;
310 long start; 327 long start;
311 long step; 328 long step;
312 long len; 329 long len;
313 } rangeiterobject; 330 } rangeiterobject;
314 331
315 static PyObject * 332 static PyObject *
316 rangeiter_next(rangeiterobject *r) 333 rangeiter_next(rangeiterobject *r)
317 { 334 {
318 if (r->index < r->len) 335 if (r->index < r->len)
319 return PyLong_FromLong(r->start + (r->index++) * r->step); 336 return PyLong_FromLong(r->start + (r->index++) * r->step);
320 return NULL; 337 return NULL;
321 } 338 }
322 339
323 static PyObject * 340 static PyObject *
324 rangeiter_len(rangeiterobject *r) 341 rangeiter_len(rangeiterobject *r)
325 { 342 {
326 return PyLong_FromLong(r->len - r->index); 343 return PyLong_FromLong(r->len - r->index);
327 } 344 }
328 345
329 typedef struct { 346 typedef struct {
330 PyObject_HEAD 347 PyObject_HEAD
331 PyObject *index; 348 PyObject *index;
332 PyObject *start; 349 PyObject *start;
333 PyObject *step; 350 PyObject *step;
334 PyObject *len; 351 PyObject *len;
335 } longrangeiterobject; 352 } longrangeiterobject;
336 353
337 static PyObject * 354 static PyObject *
338 longrangeiter_len(longrangeiterobject *r, PyObject *no_args) 355 longrangeiter_len(longrangeiterobject *r, PyObject *no_args)
339 { 356 {
(...skipping 244 matching lines...) Show 10 above Show 10 below
584 it->index = PyLong_FromLong(0); 601 it->index = PyLong_FromLong(0);
585 if (!it->index) 602 if (!it->index)
586 goto create_failure; 603 goto create_failure;
587 604
588 return (PyObject *)it; 605 return (PyObject *)it;
589 606
590 create_failure: 607 create_failure:
591 Py_DECREF(it); 608 Py_DECREF(it);
592 return NULL; 609 return NULL;
593 } 610 }
594 611
595 static PyObject * 612 static PyObject *
596 range_reverse(PyObject *seq) 613 range_reverse(PyObject *seq)
597 { 614 {
598 rangeobject *range = (rangeobject*) seq; 615 rangeobject *range = (rangeobject*) seq;
599 longrangeiterobject *it; 616 longrangeiterobject *it;
600 PyObject *one, *sum, *diff, *len = NULL, *product; 617 PyObject *one, *sum, *diff, *len = NULL, *product;
601 long lstart, lstop, lstep; 618 long lstart, lstop, lstep;
602 619
603 /* XXX(nnorwitz): do the calc for the new start/stop first, 620 /* XXX(nnorwitz): do the calc for the new start/stop first,
604 then if they fit, call the proper iter()? 621 then if they fit, call the proper iter()?
605 */ 622 */
606 assert(PyRange_Check(seq)); 623 assert(PyRange_Check(seq));
607 624
608 /* If all three fields convert to long, use the int version */ 625 /* If all three fields convert to long, use the int version */
609 lstart = PyLong_AsLong(range->start); 626 lstart = PyLong_AsLong(range->start);
610 if (lstart != -1 || !PyErr_Occurred()) { 627 if (lstart != -1 || !PyErr_Occurred()) {
611 lstop = PyLong_AsLong(range->stop); 628 lstop = PyLong_AsLong(range->stop);
612 if (lstop != -1 || !PyErr_Occurred()) { 629 if (lstop != -1 || !PyErr_Occurred()) {
613 lstep = PyLong_AsLong(range->step); 630 lstep = PyLong_AsLong(range->step);
614 if (lstep != -1 || !PyErr_Occurred()) { 631 if (lstep != -1 || !PyErr_Occurred()) {
615 /* XXX(nnorwitz): need to check for overflow and simplify. */ 632 /* XXX(nnorwitz): need to check for overflow and simplify. */
616 long len = get_len_of_range(lstart, lstop, lstep); 633 long len = get_len_of_range(lstart, lstop, lstep);
617 long new_start = lstart + (len - 1) * lstep; 634 long new_start = lstart + (len - 1) * lstep;
618 long new_stop = lstart; 635 long new_stop = lstart;
619 if (lstep > 0) 636 if (lstep > 0)
620 new_stop -= 1; 637 new_stop -= 1;
621 else 638 else
622 new_stop += 1; 639 new_stop += 1;
623 return int_range_iter(new_start, new_stop, -lstep); 640 return int_range_iter(new_start, new_stop, -lstep);
624 } 641 }
625 } 642 }
626 } 643 }
627 PyErr_Clear(); 644 PyErr_Clear();
628 645
629 it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type); 646 it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type);
630 if (it == NULL) 647 if (it == NULL)
631 return NULL; 648 return NULL;
632 649
633 /* start + (len - 1) * step */ 650 /* start + (len - 1) * step */
634 len = range->length; 651 len = range->length;
mvloewis 2008/05/02 20:17:20 You need to INCREF, since you are a) going to DECR
635 652
636 one = PyLong_FromLong(1); 653 one = PyLong_FromLong(1);
637 if (!one) 654 if (!one)
638 goto create_failure; 655 goto create_failure;
639 656
640 diff = PyNumber_Subtract(len, one); 657 diff = PyNumber_Subtract(len, one);
641 Py_DECREF(one); 658 Py_DECREF(one);
642 if (!diff) 659 if (!diff)
643 goto create_failure; 660 goto create_failure;
644 661
645 product = PyNumber_Multiply(len, range->step); 662 product = PyNumber_Multiply(len, range->step);
646 if (!product) 663 if (!product)
647 goto create_failure; 664 goto create_failure;
648 665
649 sum = PyNumber_Add(range->start, product); 666 sum = PyNumber_Add(range->start, product);
650 Py_DECREF(product); 667 Py_DECREF(product);
651 it->start = sum; 668 it->start = sum;
652 if (!it->start) 669 if (!it->start)
653 goto create_failure; 670 goto create_failure;
654 it->step = PyNumber_Negative(range->step); 671 it->step = PyNumber_Negative(range->step);
655 if (!it->step) { 672 if (!it->step) {
656 Py_DECREF(it->start); 673 Py_DECREF(it->start);
657 PyObject_Del(it); 674 PyObject_Del(it);