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

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