| 
									
										
										
										
											1993-10-26 17:58:25 +00:00
										 |  |  | /* Range object implementation */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-05-02 03:12:38 +00:00
										 |  |  | #include "Python.h"
 | 
					
						
							| 
									
										
										
										
											2001-07-09 12:30:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | /* Support objects whose length is > PY_SSIZE_T_MAX.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    This could be sped up for small PyLongs if they fit in an Py_ssize_t. | 
					
						
							|  |  |  |    This only matters on Win64.  Though we could use PY_LONG_LONG which | 
					
						
							|  |  |  |    would presumably help perf. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1993-10-26 17:58:25 +00:00
										 |  |  | typedef struct { | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     PyObject_HEAD | 
					
						
							|  |  |  |     PyObject *start; | 
					
						
							|  |  |  |     PyObject *stop; | 
					
						
							|  |  |  |     PyObject *step; | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |     PyObject *length; | 
					
						
							| 
									
										
										
										
											1993-10-26 17:58:25 +00:00
										 |  |  | } rangeobject; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | /* Helper function for validating step.  Always returns a new reference or
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |    NULL on error. | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | */ | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2010-11-20 23:05:39 +00:00
										 |  |  | validate_step(PyObject *step) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     /* No step specified, use a step of 1. */ | 
					
						
							|  |  |  |     if (!step) | 
					
						
							| 
									
										
										
										
											2007-12-02 14:31:20 +00:00
										 |  |  |         return PyLong_FromLong(1); | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     step = PyNumber_Index(step); | 
					
						
							|  |  |  |     if (step) { | 
					
						
							|  |  |  |         Py_ssize_t istep = PyNumber_AsSsize_t(step, NULL); | 
					
						
							|  |  |  |         if (istep == -1 && PyErr_Occurred()) { | 
					
						
							|  |  |  |             /* Ignore OverflowError, we know the value isn't 0. */ | 
					
						
							|  |  |  |             PyErr_Clear(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else if (istep == 0) { | 
					
						
							|  |  |  |             PyErr_SetString(PyExc_ValueError, | 
					
						
							|  |  |  |                             "range() arg 3 must not be zero"); | 
					
						
							|  |  |  |             Py_CLEAR(step); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return step; | 
					
						
							| 
									
										
										
										
											2002-06-05 23:12:45 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | compute_range_length(PyObject *start, PyObject *stop, PyObject *step); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static rangeobject * | 
					
						
							|  |  |  | make_range_object(PyTypeObject *type, PyObject *start, | 
					
						
							|  |  |  |                   PyObject *stop, PyObject *step) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     rangeobject *obj = NULL; | 
					
						
							|  |  |  |     PyObject *length; | 
					
						
							|  |  |  |     length = compute_range_length(start, stop, step); | 
					
						
							|  |  |  |     if (length == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     obj = PyObject_New(rangeobject, type); | 
					
						
							|  |  |  |     if (obj == NULL) { | 
					
						
							|  |  |  |         Py_DECREF(length); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     obj->start = start; | 
					
						
							|  |  |  |     obj->stop = stop; | 
					
						
							|  |  |  |     obj->step = step; | 
					
						
							|  |  |  |     obj->length = length; | 
					
						
							|  |  |  |     return obj; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | /* XXX(nnorwitz): should we error check if the user passes any empty ranges?
 | 
					
						
							|  |  |  |    range(-10) | 
					
						
							|  |  |  |    range(0, -5) | 
					
						
							|  |  |  |    range(0, 5, -1) | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2002-06-05 23:12:45 +00:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2010-11-20 23:05:39 +00:00
										 |  |  | range_new(PyTypeObject *type, PyObject *args, PyObject *kw) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |     rangeobject *obj; | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     PyObject *start = NULL, *stop = NULL, *step = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!_PyArg_NoKeywords("range()", kw)) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (PyTuple_Size(args) <= 1) { | 
					
						
							|  |  |  |         if (!PyArg_UnpackTuple(args, "range", 1, 1, &stop)) | 
					
						
							| 
									
										
										
										
											2009-06-12 18:40:16 +00:00
										 |  |  |             return NULL; | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |         stop = PyNumber_Index(stop); | 
					
						
							|  |  |  |         if (!stop) | 
					
						
							| 
									
										
										
										
											2009-06-12 18:40:16 +00:00
										 |  |  |             return NULL; | 
					
						
							| 
									
										
										
										
											2007-12-02 14:31:20 +00:00
										 |  |  |         start = PyLong_FromLong(0); | 
					
						
							| 
									
										
										
										
											2009-06-12 18:40:16 +00:00
										 |  |  |         if (!start) { | 
					
						
							|  |  |  |             Py_DECREF(stop); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2007-12-02 14:31:20 +00:00
										 |  |  |         step = PyLong_FromLong(1); | 
					
						
							| 
									
										
										
										
											2009-06-12 18:40:16 +00:00
										 |  |  |         if (!step) { | 
					
						
							|  |  |  |             Py_DECREF(stop); | 
					
						
							|  |  |  |             Py_DECREF(start); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         if (!PyArg_UnpackTuple(args, "range", 2, 3, | 
					
						
							|  |  |  |                                &start, &stop, &step)) | 
					
						
							| 
									
										
										
										
											2009-06-12 18:40:16 +00:00
										 |  |  |             return NULL; | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         /* Convert borrowed refs to owned refs */ | 
					
						
							|  |  |  |         start = PyNumber_Index(start); | 
					
						
							| 
									
										
										
										
											2009-06-12 18:40:16 +00:00
										 |  |  |         if (!start) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |         stop = PyNumber_Index(stop); | 
					
						
							| 
									
										
										
										
											2009-06-12 18:40:16 +00:00
										 |  |  |         if (!stop) { | 
					
						
							|  |  |  |             Py_DECREF(start); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         step = validate_step(step);    /* Caution, this can clear exceptions */ | 
					
						
							|  |  |  |         if (!step) { | 
					
						
							|  |  |  |             Py_DECREF(start); | 
					
						
							|  |  |  |             Py_DECREF(stop); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |     obj = make_range_object(type, start, stop, step); | 
					
						
							|  |  |  |     if (obj != NULL) | 
					
						
							|  |  |  |         return (PyObject *) obj; | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |     /* Failed to create object, release attributes */ | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     Py_XDECREF(start); | 
					
						
							|  |  |  |     Py_XDECREF(stop); | 
					
						
							|  |  |  |     Py_XDECREF(step); | 
					
						
							|  |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2002-06-05 23:12:45 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-06-13 20:33:02 +00:00
										 |  |  | PyDoc_STRVAR(range_doc, | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | "range([start,] stop[, step]) -> range object\n\
 | 
					
						
							| 
									
										
										
										
											2002-06-05 23:12:45 +00:00
										 |  |  | \n\ | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  | Returns a virtual sequence of numbers from start to stop by step."); | 
					
						
							| 
									
										
										
										
											2002-06-05 23:12:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | static void | 
					
						
							| 
									
										
										
										
											2010-11-20 23:05:39 +00:00
										 |  |  | range_dealloc(rangeobject *r) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     Py_DECREF(r->start); | 
					
						
							|  |  |  |     Py_DECREF(r->stop); | 
					
						
							|  |  |  |     Py_DECREF(r->step); | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |     Py_DECREF(r->length); | 
					
						
							| 
									
										
										
										
											2007-11-15 20:52:21 +00:00
										 |  |  |     PyObject_Del(r); | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-28 22:08:40 +00:00
										 |  |  | /* Return number of items in range (lo, hi, step) as a PyLong object,
 | 
					
						
							|  |  |  |  * when arguments are PyLong objects.  Arguments MUST return 1 with | 
					
						
							|  |  |  |  * PyLong_Check().  Return NULL when there is an error. | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | static PyObject* | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  | compute_range_length(PyObject *start, PyObject *stop, PyObject *step) | 
					
						
							| 
									
										
										
										
											2010-11-20 23:05:39 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     /* -------------------------------------------------------------
 | 
					
						
							|  |  |  |     Algorithm is equal to that of get_len_of_range(), but it operates | 
					
						
							| 
									
										
										
										
											2009-06-24 21:14:38 +00:00
										 |  |  |     on PyObjects (which are assumed to be PyLong objects). | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     ---------------------------------------------------------------*/ | 
					
						
							| 
									
										
										
										
											2009-02-01 10:28:51 +00:00
										 |  |  |     int cmp_result; | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     PyObject *lo, *hi; | 
					
						
							|  |  |  |     PyObject *diff = NULL; | 
					
						
							|  |  |  |     PyObject *one = NULL; | 
					
						
							|  |  |  |     PyObject *tmp1 = NULL, *tmp2 = NULL, *result; | 
					
						
							|  |  |  |                 /* holds sub-expression evaluations */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PyObject *zero = PyLong_FromLong(0); | 
					
						
							|  |  |  |     if (zero == NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |     cmp_result = PyObject_RichCompareBool(step, zero, Py_GT); | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     Py_DECREF(zero); | 
					
						
							| 
									
										
										
										
											2009-02-01 10:28:51 +00:00
										 |  |  |     if (cmp_result == -1) | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-01 10:28:51 +00:00
										 |  |  |     if (cmp_result == 1) { | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |         lo = start; | 
					
						
							|  |  |  |         hi = stop; | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |         Py_INCREF(step); | 
					
						
							|  |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |         lo = stop; | 
					
						
							|  |  |  |         hi = start; | 
					
						
							|  |  |  |         step = PyNumber_Negative(step); | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |         if (!step) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* if (lo >= hi), return length of 0. */ | 
					
						
							| 
									
										
										
										
											2009-02-01 10:28:51 +00:00
										 |  |  |     if (PyObject_RichCompareBool(lo, hi, Py_GE) == 1) { | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |         Py_XDECREF(step); | 
					
						
							|  |  |  |         return PyLong_FromLong(0); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((one = PyLong_FromLong(1L)) == NULL) | 
					
						
							|  |  |  |         goto Fail; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((tmp1 = PyNumber_Subtract(hi, lo)) == NULL) | 
					
						
							|  |  |  |         goto Fail; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((diff = PyNumber_Subtract(tmp1, one)) == NULL) | 
					
						
							|  |  |  |         goto Fail; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((tmp2 = PyNumber_FloorDivide(diff, step)) == NULL) | 
					
						
							|  |  |  |         goto Fail; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((result = PyNumber_Add(tmp2, one)) == NULL) | 
					
						
							|  |  |  |         goto Fail; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_DECREF(tmp2); | 
					
						
							|  |  |  |     Py_DECREF(diff); | 
					
						
							|  |  |  |     Py_DECREF(step); | 
					
						
							|  |  |  |     Py_DECREF(tmp1); | 
					
						
							|  |  |  |     Py_DECREF(one); | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Fail: | 
					
						
							|  |  |  |     Py_XDECREF(tmp2); | 
					
						
							|  |  |  |     Py_XDECREF(diff); | 
					
						
							|  |  |  |     Py_XDECREF(step); | 
					
						
							|  |  |  |     Py_XDECREF(tmp1); | 
					
						
							|  |  |  |     Py_XDECREF(one); | 
					
						
							|  |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											1993-10-26 17:58:25 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | static Py_ssize_t | 
					
						
							| 
									
										
										
										
											2010-11-20 23:05:39 +00:00
										 |  |  | range_length(rangeobject *r) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |     return PyLong_AsSsize_t(r->length); | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2011-01-12 03:15:52 +00:00
										 |  |  | compute_item(rangeobject *r, PyObject *i) | 
					
						
							| 
									
										
										
										
											2010-11-20 23:05:39 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-01-12 03:15:52 +00:00
										 |  |  |     PyObject *incr, *result; | 
					
						
							|  |  |  |     /* PyLong equivalent to:
 | 
					
						
							|  |  |  |      *    return r->start + (i * r->step) | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     incr = PyNumber_Multiply(i, r->step); | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     if (!incr) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     result = PyNumber_Add(r->start, incr); | 
					
						
							|  |  |  |     Py_DECREF(incr); | 
					
						
							|  |  |  |     return result; | 
					
						
							| 
									
										
										
										
											1993-12-21 22:50:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-05-02 03:12:38 +00:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2011-01-12 03:15:52 +00:00
										 |  |  | compute_range_item(rangeobject *r, PyObject *arg) | 
					
						
							| 
									
										
										
										
											2010-11-20 23:05:39 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-01-12 03:15:52 +00:00
										 |  |  |     int cmp_result; | 
					
						
							|  |  |  |     PyObject *i, *result; | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-12 03:15:52 +00:00
										 |  |  |     PyObject *zero = PyLong_FromLong(0); | 
					
						
							|  |  |  |     if (zero == NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* PyLong equivalent to:
 | 
					
						
							|  |  |  |      *   if (arg < 0) { | 
					
						
							|  |  |  |      *     i = r->length + arg | 
					
						
							|  |  |  |      *   } else { | 
					
						
							|  |  |  |      *     i = arg | 
					
						
							|  |  |  |      *   } | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     cmp_result = PyObject_RichCompareBool(arg, zero, Py_LT); | 
					
						
							|  |  |  |     if (cmp_result == -1) { | 
					
						
							|  |  |  |         Py_DECREF(zero); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (cmp_result == 1) { | 
					
						
							|  |  |  |       i = PyNumber_Add(r->length, arg); | 
					
						
							|  |  |  |       if (!i) { | 
					
						
							|  |  |  |         Py_DECREF(zero); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       i = arg; | 
					
						
							|  |  |  |       Py_INCREF(i); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2001-07-09 12:30:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-12 03:15:52 +00:00
										 |  |  |     /* PyLong equivalent to:
 | 
					
						
							|  |  |  |      *   if (i < 0 || i >= r->length) { | 
					
						
							|  |  |  |      *     <report index out of bounds> | 
					
						
							|  |  |  |      *   } | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     cmp_result = PyObject_RichCompareBool(i, zero, Py_LT); | 
					
						
							|  |  |  |     Py_DECREF(zero); | 
					
						
							|  |  |  |     if (cmp_result == 0) { | 
					
						
							|  |  |  |         cmp_result = PyObject_RichCompareBool(i, r->length, Py_GE); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (cmp_result == -1) { | 
					
						
							|  |  |  |        Py_DECREF(i); | 
					
						
							|  |  |  |        return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (cmp_result == 1) { | 
					
						
							|  |  |  |         Py_DECREF(i); | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_IndexError, | 
					
						
							|  |  |  |                         "range object index out of range"); | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-01-12 03:15:52 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     result = compute_item(r, i); | 
					
						
							|  |  |  |     Py_DECREF(i); | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | range_item(rangeobject *r, Py_ssize_t i) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-01-13 04:22:54 +00:00
										 |  |  |     PyObject *res, *arg = PyLong_FromLong(i); | 
					
						
							| 
									
										
										
										
											2011-01-12 03:15:52 +00:00
										 |  |  |     if (!arg) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-01-13 04:22:54 +00:00
										 |  |  |     res = compute_range_item(r, arg); | 
					
						
							|  |  |  |     Py_DECREF(arg); | 
					
						
							|  |  |  |     return res; | 
					
						
							| 
									
										
										
										
											2011-01-12 03:15:52 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Additional helpers, since the standard slice helpers
 | 
					
						
							|  |  |  |  * all clip to PY_SSIZE_T_MAX | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Replace _PyEval_SliceIndex */ | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | compute_slice_element(PyObject *obj) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyObject *result = NULL; | 
					
						
							|  |  |  |     if (obj != NULL) { | 
					
						
							|  |  |  |         if (PyIndex_Check(obj)) { | 
					
						
							|  |  |  |             result = PyNumber_Index(obj); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (result == NULL) { | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_TypeError, | 
					
						
							|  |  |  |                         "slice indices must be integers or " | 
					
						
							|  |  |  |                         "None or have an __index__ method"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Replace PySlice_GetIndicesEx
 | 
					
						
							|  |  |  |  *   Result indicates whether or not the slice is empty | 
					
						
							|  |  |  |  *    (-1 = error, 0 = empty slice, 1 = slice contains elements) | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2011-01-16 20:57:01 +00:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2011-01-12 03:15:52 +00:00
										 |  |  | compute_slice_indices(rangeobject *r, PySliceObject *slice, | 
					
						
							|  |  |  |                       PyObject **start, PyObject **stop, PyObject **step) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int cmp_result, has_elements; | 
					
						
							|  |  |  |     Py_ssize_t clamped_step = 0; | 
					
						
							|  |  |  |     PyObject *zero = NULL, *one = NULL, *neg_one = NULL, *candidate = NULL; | 
					
						
							|  |  |  |     PyObject *tmp_start = NULL, *tmp_stop = NULL, *tmp_step = NULL; | 
					
						
							|  |  |  |     zero = PyLong_FromLong(0); | 
					
						
							|  |  |  |     if (zero == NULL) goto Fail; | 
					
						
							|  |  |  |     one = PyLong_FromLong(1); | 
					
						
							|  |  |  |     if (one == NULL) goto Fail; | 
					
						
							|  |  |  |     neg_one = PyLong_FromLong(-1); | 
					
						
							|  |  |  |     if (neg_one == NULL) goto Fail; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Calculate step value */ | 
					
						
							|  |  |  |     if (slice->step == Py_None) { | 
					
						
							|  |  |  |         clamped_step = 1; | 
					
						
							|  |  |  |         tmp_step = one; | 
					
						
							|  |  |  |         Py_INCREF(tmp_step); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         if (!_PyEval_SliceIndex(slice->step, &clamped_step)) goto Fail; | 
					
						
							|  |  |  |         if (clamped_step == 0) { | 
					
						
							|  |  |  |             PyErr_SetString(PyExc_ValueError, | 
					
						
							|  |  |  |                             "slice step cannot be zero"); | 
					
						
							|  |  |  |             goto Fail; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         tmp_step = compute_slice_element(slice->step); | 
					
						
							|  |  |  |         if (tmp_step == NULL) goto Fail; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Calculate start value */ | 
					
						
							|  |  |  |     if (slice->start == Py_None) { | 
					
						
							|  |  |  |         if (clamped_step < 0) { | 
					
						
							|  |  |  |             tmp_start = PyNumber_Subtract(r->length, one); | 
					
						
							|  |  |  |             if (tmp_start == NULL) goto Fail; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             tmp_start = zero; | 
					
						
							|  |  |  |             Py_INCREF(tmp_start); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         candidate = compute_slice_element(slice->start); | 
					
						
							|  |  |  |         if (candidate == NULL) goto Fail; | 
					
						
							|  |  |  |         cmp_result = PyObject_RichCompareBool(candidate, zero, Py_LT); | 
					
						
							|  |  |  |         if (cmp_result == -1) goto Fail; | 
					
						
							|  |  |  |         if (cmp_result) { | 
					
						
							|  |  |  |             /* candidate < 0 */ | 
					
						
							|  |  |  |             tmp_start = PyNumber_Add(r->length, candidate); | 
					
						
							|  |  |  |             if (tmp_start == NULL) goto Fail; | 
					
						
							|  |  |  |             Py_CLEAR(candidate); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             /* candidate >= 0 */ | 
					
						
							|  |  |  |             tmp_start = candidate; | 
					
						
							|  |  |  |             candidate = NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         cmp_result = PyObject_RichCompareBool(tmp_start, zero, Py_LT); | 
					
						
							|  |  |  |         if (cmp_result == -1) goto Fail; | 
					
						
							|  |  |  |         if (cmp_result) { | 
					
						
							|  |  |  |             /* tmp_start < 0 */ | 
					
						
							|  |  |  |             Py_CLEAR(tmp_start); | 
					
						
							|  |  |  |             if (clamped_step < 0) { | 
					
						
							|  |  |  |                 tmp_start = neg_one; | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 tmp_start = zero; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             Py_INCREF(tmp_start); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             /* tmp_start >= 0 */ | 
					
						
							|  |  |  |             cmp_result = PyObject_RichCompareBool(tmp_start, r->length, Py_GE); | 
					
						
							|  |  |  |             if (cmp_result == -1) goto Fail; | 
					
						
							|  |  |  |             if (cmp_result) { | 
					
						
							|  |  |  |                 /* tmp_start >= r->length */ | 
					
						
							|  |  |  |                 Py_CLEAR(tmp_start); | 
					
						
							|  |  |  |                 if (clamped_step < 0) { | 
					
						
							|  |  |  |                     tmp_start = PyNumber_Subtract(r->length, one); | 
					
						
							|  |  |  |                     if (tmp_start == NULL) goto Fail; | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     tmp_start = r->length; | 
					
						
							|  |  |  |                     Py_INCREF(tmp_start); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Calculate stop value */ | 
					
						
							|  |  |  |     if (slice->stop == Py_None) { | 
					
						
							|  |  |  |         if (clamped_step < 0) { | 
					
						
							|  |  |  |             tmp_stop = neg_one; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             tmp_stop = r->length; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         Py_INCREF(tmp_stop); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         candidate = compute_slice_element(slice->stop); | 
					
						
							|  |  |  |         if (candidate == NULL) goto Fail; | 
					
						
							|  |  |  |         cmp_result = PyObject_RichCompareBool(candidate, zero, Py_LT); | 
					
						
							|  |  |  |         if (cmp_result == -1) goto Fail; | 
					
						
							|  |  |  |         if (cmp_result) { | 
					
						
							|  |  |  |             /* candidate < 0 */ | 
					
						
							|  |  |  |             tmp_stop = PyNumber_Add(r->length, candidate); | 
					
						
							|  |  |  |             if (tmp_stop == NULL) goto Fail; | 
					
						
							|  |  |  |             Py_CLEAR(candidate); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             /* candidate >= 0 */ | 
					
						
							|  |  |  |             tmp_stop = candidate; | 
					
						
							|  |  |  |             candidate = NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         cmp_result = PyObject_RichCompareBool(tmp_stop, zero, Py_LT); | 
					
						
							|  |  |  |         if (cmp_result == -1) goto Fail; | 
					
						
							|  |  |  |         if (cmp_result) { | 
					
						
							|  |  |  |             /* tmp_stop < 0 */ | 
					
						
							|  |  |  |             Py_CLEAR(tmp_stop); | 
					
						
							|  |  |  |             if (clamped_step < 0) { | 
					
						
							|  |  |  |                 tmp_stop = neg_one; | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 tmp_stop = zero; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             Py_INCREF(tmp_stop); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             /* tmp_stop >= 0 */ | 
					
						
							|  |  |  |             cmp_result = PyObject_RichCompareBool(tmp_stop, r->length, Py_GE); | 
					
						
							|  |  |  |             if (cmp_result == -1) goto Fail; | 
					
						
							|  |  |  |             if (cmp_result) { | 
					
						
							|  |  |  |                 /* tmp_stop >= r->length */ | 
					
						
							|  |  |  |                 Py_CLEAR(tmp_stop); | 
					
						
							|  |  |  |                 if (clamped_step < 0) { | 
					
						
							|  |  |  |                     tmp_stop = PyNumber_Subtract(r->length, one); | 
					
						
							|  |  |  |                     if (tmp_stop == NULL) goto Fail; | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     tmp_stop = r->length; | 
					
						
							| 
									
										
										
										
											2011-04-15 08:15:40 +03:00
										 |  |  |                     Py_INCREF(tmp_stop); | 
					
						
							| 
									
										
										
										
											2011-01-12 03:15:52 +00:00
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Check if the slice is empty or not */ | 
					
						
							|  |  |  |     if (clamped_step < 0) { | 
					
						
							|  |  |  |         has_elements = PyObject_RichCompareBool(tmp_start, tmp_stop, Py_GT); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         has_elements = PyObject_RichCompareBool(tmp_start, tmp_stop, Py_LT); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (has_elements == -1) goto Fail; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     *start = tmp_start; | 
					
						
							|  |  |  |     *stop = tmp_stop; | 
					
						
							|  |  |  |     *step = tmp_step; | 
					
						
							|  |  |  |     Py_DECREF(neg_one); | 
					
						
							|  |  |  |     Py_DECREF(one); | 
					
						
							|  |  |  |     Py_DECREF(zero); | 
					
						
							|  |  |  |     return has_elements; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Fail: | 
					
						
							|  |  |  |     Py_XDECREF(tmp_start); | 
					
						
							|  |  |  |     Py_XDECREF(tmp_stop); | 
					
						
							|  |  |  |     Py_XDECREF(tmp_step); | 
					
						
							|  |  |  |     Py_XDECREF(candidate); | 
					
						
							|  |  |  |     Py_XDECREF(neg_one); | 
					
						
							|  |  |  |     Py_XDECREF(one); | 
					
						
							|  |  |  |     Py_XDECREF(zero); | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | compute_slice(rangeobject *r, PyObject *_slice) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PySliceObject *slice = (PySliceObject *) _slice; | 
					
						
							|  |  |  |     rangeobject *result; | 
					
						
							|  |  |  |     PyObject *start = NULL, *stop = NULL, *step = NULL; | 
					
						
							|  |  |  |     PyObject *substart = NULL, *substop = NULL, *substep = NULL; | 
					
						
							|  |  |  |     int has_elements; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     has_elements = compute_slice_indices(r, slice, &start, &stop, &step); | 
					
						
							|  |  |  |     if (has_elements == -1) return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     substep = PyNumber_Multiply(r->step, step); | 
					
						
							|  |  |  |     if (substep == NULL) goto fail; | 
					
						
							|  |  |  |     Py_CLEAR(step); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     substart = compute_item(r, start); | 
					
						
							|  |  |  |     if (substart == NULL) goto fail; | 
					
						
							|  |  |  |     Py_CLEAR(start); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (has_elements) { | 
					
						
							|  |  |  |         substop = compute_item(r, stop); | 
					
						
							|  |  |  |         if (substop == NULL) goto fail; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         substop = substart; | 
					
						
							|  |  |  |         Py_INCREF(substop); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Py_CLEAR(stop); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     result = make_range_object(Py_TYPE(r), substart, substop, substep); | 
					
						
							|  |  |  |     if (result != NULL) { | 
					
						
							|  |  |  |         return (PyObject *) result; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | fail: | 
					
						
							|  |  |  |     Py_XDECREF(start); | 
					
						
							|  |  |  |     Py_XDECREF(stop); | 
					
						
							|  |  |  |     Py_XDECREF(step); | 
					
						
							|  |  |  |     Py_XDECREF(substart); | 
					
						
							|  |  |  |     Py_XDECREF(substop); | 
					
						
							|  |  |  |     Py_XDECREF(substep); | 
					
						
							|  |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2008-06-10 04:03:04 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-13 21:16:29 +00:00
										 |  |  | /* Assumes (PyLong_CheckExact(ob) || PyBool_Check(ob)) */ | 
					
						
							|  |  |  | static int | 
					
						
							| 
									
										
										
										
											2010-11-20 23:05:39 +00:00
										 |  |  | range_contains_long(rangeobject *r, PyObject *ob) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-09-13 21:16:29 +00:00
										 |  |  |     int cmp1, cmp2, cmp3; | 
					
						
							|  |  |  |     PyObject *tmp1 = NULL; | 
					
						
							|  |  |  |     PyObject *tmp2 = NULL; | 
					
						
							|  |  |  |     PyObject *zero = NULL; | 
					
						
							|  |  |  |     int result = -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     zero = PyLong_FromLong(0); | 
					
						
							|  |  |  |     if (zero == NULL) /* MemoryError in int(0) */ | 
					
						
							|  |  |  |         goto end; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Check if the value can possibly be in the range. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cmp1 = PyObject_RichCompareBool(r->step, zero, Py_GT); | 
					
						
							|  |  |  |     if (cmp1 == -1) | 
					
						
							|  |  |  |         goto end; | 
					
						
							|  |  |  |     if (cmp1 == 1) { /* positive steps: start <= ob < stop */ | 
					
						
							|  |  |  |         cmp2 = PyObject_RichCompareBool(r->start, ob, Py_LE); | 
					
						
							|  |  |  |         cmp3 = PyObject_RichCompareBool(ob, r->stop, Py_LT); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { /* negative steps: stop < ob <= start */ | 
					
						
							|  |  |  |         cmp2 = PyObject_RichCompareBool(ob, r->start, Py_LE); | 
					
						
							|  |  |  |         cmp3 = PyObject_RichCompareBool(r->stop, ob, Py_LT); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (cmp2 == -1 || cmp3 == -1) /* TypeError */ | 
					
						
							|  |  |  |         goto end; | 
					
						
							|  |  |  |     if (cmp2 == 0 || cmp3 == 0) { /* ob outside of range */ | 
					
						
							|  |  |  |         result = 0; | 
					
						
							|  |  |  |         goto end; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Check that the stride does not invalidate ob's membership. */ | 
					
						
							|  |  |  |     tmp1 = PyNumber_Subtract(ob, r->start); | 
					
						
							|  |  |  |     if (tmp1 == NULL) | 
					
						
							|  |  |  |         goto end; | 
					
						
							|  |  |  |     tmp2 = PyNumber_Remainder(tmp1, r->step); | 
					
						
							|  |  |  |     if (tmp2 == NULL) | 
					
						
							|  |  |  |         goto end; | 
					
						
							|  |  |  |     /* result = (int(ob) - start % step) == 0 */ | 
					
						
							|  |  |  |     result = PyObject_RichCompareBool(tmp2, zero, Py_EQ); | 
					
						
							|  |  |  |   end: | 
					
						
							|  |  |  |     Py_XDECREF(tmp1); | 
					
						
							|  |  |  |     Py_XDECREF(tmp2); | 
					
						
							|  |  |  |     Py_XDECREF(zero); | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-22 21:47:24 +00:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2010-11-20 23:05:39 +00:00
										 |  |  | range_contains(rangeobject *r, PyObject *ob) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-09-13 21:16:29 +00:00
										 |  |  |     if (PyLong_CheckExact(ob) || PyBool_Check(ob)) | 
					
						
							|  |  |  |         return range_contains_long(r, ob); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return (int)_PySequence_IterSearch((PyObject*)r, ob, | 
					
						
							|  |  |  |                                        PY_ITERSEARCH_CONTAINS); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2010-11-20 23:05:39 +00:00
										 |  |  | range_count(rangeobject *r, PyObject *ob) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-09-24 20:04:23 +00:00
										 |  |  |     if (PyLong_CheckExact(ob) || PyBool_Check(ob)) { | 
					
						
							| 
									
										
										
										
											2010-11-20 22:40:10 +00:00
										 |  |  |         int result = range_contains_long(r, ob); | 
					
						
							|  |  |  |         if (result == -1) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         else if (result) | 
					
						
							| 
									
										
										
										
											2010-11-20 22:35:41 +00:00
										 |  |  |             return PyLong_FromLong(1); | 
					
						
							| 
									
										
										
										
											2010-09-13 21:16:29 +00:00
										 |  |  |         else | 
					
						
							| 
									
										
										
										
											2010-11-20 22:35:41 +00:00
										 |  |  |             return PyLong_FromLong(0); | 
					
						
							| 
									
										
										
										
											2010-09-13 21:16:29 +00:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         Py_ssize_t count; | 
					
						
							|  |  |  |         count = _PySequence_IterSearch((PyObject*)r, ob, PY_ITERSEARCH_COUNT); | 
					
						
							|  |  |  |         if (count == -1) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         return PyLong_FromSsize_t(count); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-09-22 21:47:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-13 21:16:29 +00:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2010-11-20 23:05:39 +00:00
										 |  |  | range_index(rangeobject *r, PyObject *ob) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-09-13 21:16:29 +00:00
										 |  |  |     int contains; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!PyLong_CheckExact(ob) && !PyBool_Check(ob)) { | 
					
						
							|  |  |  |         Py_ssize_t index; | 
					
						
							|  |  |  |         index = _PySequence_IterSearch((PyObject*)r, ob, PY_ITERSEARCH_INDEX); | 
					
						
							|  |  |  |         if (index == -1) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         return PyLong_FromSsize_t(index); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     contains = range_contains_long(r, ob); | 
					
						
							|  |  |  |     if (contains == -1) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-20 22:44:32 +00:00
										 |  |  |     if (contains) { | 
					
						
							|  |  |  |         PyObject *idx, *tmp = PyNumber_Subtract(ob, r->start); | 
					
						
							|  |  |  |         if (tmp == NULL) | 
					
						
							| 
									
										
										
										
											2010-09-13 21:16:29 +00:00
										 |  |  |             return NULL; | 
					
						
							| 
									
										
										
										
											2010-11-20 22:44:32 +00:00
										 |  |  |         /* idx = (ob - r.start) // r.step */ | 
					
						
							|  |  |  |         idx = PyNumber_FloorDivide(tmp, r->step); | 
					
						
							|  |  |  |         Py_DECREF(tmp); | 
					
						
							|  |  |  |         return idx; | 
					
						
							| 
									
										
										
										
											2009-09-22 21:47:24 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-11-20 22:44:32 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* object is not in the range */ | 
					
						
							|  |  |  |     PyErr_Format(PyExc_ValueError, "%R is not in range", ob); | 
					
						
							| 
									
										
										
										
											2010-09-13 21:16:29 +00:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2009-09-22 21:47:24 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-05-02 03:12:38 +00:00
										 |  |  | static PySequenceMethods range_as_sequence = { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     (lenfunc)range_length,      /* sq_length */ | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |     0,                          /* sq_concat */ | 
					
						
							|  |  |  |     0,                          /* sq_repeat */ | 
					
						
							|  |  |  |     (ssizeargfunc)range_item,   /* sq_item */ | 
					
						
							|  |  |  |     0,                          /* sq_slice */ | 
					
						
							|  |  |  |     0,                          /* sq_ass_item */ | 
					
						
							|  |  |  |     0,                          /* sq_ass_slice */ | 
					
						
							| 
									
										
										
										
											2009-09-22 21:47:24 +00:00
										 |  |  |     (objobjproc)range_contains, /* sq_contains */ | 
					
						
							| 
									
										
										
										
											1993-10-26 17:58:25 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | range_repr(rangeobject *r) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Py_ssize_t istep; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Check for special case values for printing.  We don't always
 | 
					
						
							|  |  |  |        need the step value.  We don't care about errors | 
					
						
							|  |  |  |        (it means overflow), so clear the errors. */ | 
					
						
							|  |  |  |     istep = PyNumber_AsSsize_t(r->step, NULL); | 
					
						
							|  |  |  |     if (istep != 1 || (istep == -1 && PyErr_Occurred())) { | 
					
						
							|  |  |  |         PyErr_Clear(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (istep == 1) | 
					
						
							|  |  |  |         return PyUnicode_FromFormat("range(%R, %R)", r->start, r->stop); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         return PyUnicode_FromFormat("range(%R, %R, %R)", | 
					
						
							|  |  |  |                                     r->start, r->stop, r->step); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Pickling support */ | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | range_reduce(rangeobject *r, PyObject *args) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return Py_BuildValue("(O(OOO))", Py_TYPE(r), | 
					
						
							|  |  |  |                          r->start, r->stop, r->step); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | range_subscript(rangeobject* self, PyObject* item) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (PyIndex_Check(item)) { | 
					
						
							| 
									
										
										
										
											2011-01-12 03:15:52 +00:00
										 |  |  |         PyObject *i, *result; | 
					
						
							|  |  |  |         i = PyNumber_Index(item); | 
					
						
							|  |  |  |         if (!i) | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |             return NULL; | 
					
						
							| 
									
										
										
										
											2011-01-12 03:15:52 +00:00
										 |  |  |         result = compute_range_item(self, i); | 
					
						
							|  |  |  |         Py_DECREF(i); | 
					
						
							|  |  |  |         return result; | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (PySlice_Check(item)) { | 
					
						
							| 
									
										
										
										
											2011-01-12 03:15:52 +00:00
										 |  |  |         return compute_slice(self, item); | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  |                  "range indices must be integers or slices, not %.200s", | 
					
						
							|  |  |  |                  item->ob_type->tp_name); | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyMappingMethods range_as_mapping = { | 
					
						
							|  |  |  |         (lenfunc)range_length,       /* mp_length */ | 
					
						
							|  |  |  |         (binaryfunc)range_subscript, /* mp_subscript */ | 
					
						
							|  |  |  |         (objobjargproc)0,            /* mp_ass_subscript */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 16:30:39 +00:00
										 |  |  | static PyObject * range_iter(PyObject *seq); | 
					
						
							| 
									
										
										
										
											2003-11-06 14:06:48 +00:00
										 |  |  | static PyObject * range_reverse(PyObject *seq); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(reverse_doc, | 
					
						
							|  |  |  | "Returns a reverse iterator."); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-13 21:16:29 +00:00
										 |  |  | PyDoc_STRVAR(count_doc, | 
					
						
							|  |  |  | "rangeobject.count(value) -> integer -- return number of occurrences of value"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(index_doc, | 
					
						
							|  |  |  | "rangeobject.index(value, [start, [stop]]) -> integer -- return index of value.\n" | 
					
						
							|  |  |  | "Raises ValueError if the value is not present."); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-11-06 14:06:48 +00:00
										 |  |  | static PyMethodDef range_methods[] = { | 
					
						
							| 
									
										
										
										
											2010-09-13 21:16:29 +00:00
										 |  |  |     {"__reversed__",    (PyCFunction)range_reverse, METH_NOARGS, reverse_doc}, | 
					
						
							|  |  |  |     {"__reduce__",      (PyCFunction)range_reduce,  METH_VARARGS}, | 
					
						
							|  |  |  |     {"count",           (PyCFunction)range_count,   METH_O,      count_doc}, | 
					
						
							|  |  |  |     {"index",           (PyCFunction)range_index,   METH_O,      index_doc}, | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     {NULL,              NULL}           /* sentinel */ | 
					
						
							| 
									
										
										
										
											2003-11-06 14:06:48 +00:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2002-06-05 20:08:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-05-02 03:12:38 +00:00
										 |  |  | PyTypeObject PyRange_Type = { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         PyVarObject_HEAD_INIT(&PyType_Type, 0) | 
					
						
							|  |  |  |         "range",                /* Name of this type */ | 
					
						
							|  |  |  |         sizeof(rangeobject),    /* Basic object size */ | 
					
						
							|  |  |  |         0,                      /* Item size for varobject */ | 
					
						
							|  |  |  |         (destructor)range_dealloc, /* tp_dealloc */ | 
					
						
							|  |  |  |         0,                      /* tp_print */ | 
					
						
							|  |  |  |         0,                      /* tp_getattr */ | 
					
						
							|  |  |  |         0,                      /* tp_setattr */ | 
					
						
							|  |  |  |         0,                      /* tp_reserved */ | 
					
						
							|  |  |  |         (reprfunc)range_repr,   /* tp_repr */ | 
					
						
							|  |  |  |         0,                      /* tp_as_number */ | 
					
						
							|  |  |  |         &range_as_sequence,     /* tp_as_sequence */ | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |         &range_as_mapping,      /* tp_as_mapping */ | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         0,                      /* tp_hash */ | 
					
						
							|  |  |  |         0,                      /* tp_call */ | 
					
						
							|  |  |  |         0,                      /* tp_str */ | 
					
						
							|  |  |  |         PyObject_GenericGetAttr,  /* tp_getattro */ | 
					
						
							|  |  |  |         0,                      /* tp_setattro */ | 
					
						
							|  |  |  |         0,                      /* tp_as_buffer */ | 
					
						
							|  |  |  |         Py_TPFLAGS_DEFAULT,     /* tp_flags */ | 
					
						
							|  |  |  |         range_doc,              /* tp_doc */ | 
					
						
							|  |  |  |         0,                      /* tp_traverse */ | 
					
						
							|  |  |  |         0,                      /* tp_clear */ | 
					
						
							|  |  |  |         0,                      /* tp_richcompare */ | 
					
						
							|  |  |  |         0,                      /* tp_weaklistoffset */ | 
					
						
							|  |  |  |         range_iter,             /* tp_iter */ | 
					
						
							|  |  |  |         0,                      /* tp_iternext */ | 
					
						
							|  |  |  |         range_methods,          /* tp_methods */ | 
					
						
							|  |  |  |         0,                      /* tp_members */ | 
					
						
							|  |  |  |         0,                      /* tp_getset */ | 
					
						
							|  |  |  |         0,                      /* tp_base */ | 
					
						
							|  |  |  |         0,                      /* tp_dict */ | 
					
						
							|  |  |  |         0,                      /* tp_descr_get */ | 
					
						
							|  |  |  |         0,                      /* tp_descr_set */ | 
					
						
							|  |  |  |         0,                      /* tp_dictoffset */ | 
					
						
							|  |  |  |         0,                      /* tp_init */ | 
					
						
							|  |  |  |         0,                      /* tp_alloc */ | 
					
						
							|  |  |  |         range_new,              /* tp_new */ | 
					
						
							| 
									
										
										
										
											2002-06-05 20:08:48 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-21 18:01:17 +00:00
										 |  |  | /*********************** range Iterator **************************/ | 
					
						
							| 
									
										
										
										
											2002-06-05 20:08:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | /* There are 2 types of iterators, one for C longs, the other for
 | 
					
						
							|  |  |  |    Python longs (ie, PyObjects).  This should make iteration fast | 
					
						
							|  |  |  |    in the normal case, but possible for any numeric value. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-06-05 20:08:48 +00:00
										 |  |  | typedef struct { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         PyObject_HEAD | 
					
						
							|  |  |  |         long    index; | 
					
						
							|  |  |  |         long    start; | 
					
						
							|  |  |  |         long    step; | 
					
						
							|  |  |  |         long    len; | 
					
						
							| 
									
										
										
										
											2002-06-05 20:08:48 +00:00
										 |  |  | } rangeiterobject; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2010-11-20 23:05:39 +00:00
										 |  |  | rangeiter_next(rangeiterobject *r) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     if (r->index < r->len) | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         /* cast to unsigned to avoid possible signed overflow
 | 
					
						
							| 
									
										
										
										
											2009-11-15 12:56:08 +00:00
										 |  |  |            in intermediate calculations. */ | 
					
						
							|  |  |  |         return PyLong_FromLong((long)(r->start + | 
					
						
							|  |  |  |                                       (unsigned long)(r->index++) * r->step)); | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2002-06-05 20:08:48 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-09-24 21:23:05 +00:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2010-11-20 23:05:39 +00:00
										 |  |  | rangeiter_len(rangeiterobject *r) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-12-02 14:31:20 +00:00
										 |  |  |     return PyLong_FromLong(r->len - r->index); | 
					
						
							| 
									
										
										
										
											2004-03-10 10:10:42 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | PyDoc_STRVAR(length_hint_doc, | 
					
						
							|  |  |  |              "Private method returning an estimate of len(list(it))."); | 
					
						
							| 
									
										
										
										
											2004-03-10 10:10:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-09-24 21:23:05 +00:00
										 |  |  | static PyMethodDef rangeiter_methods[] = { | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     {"__length_hint__", (PyCFunction)rangeiter_len, METH_NOARGS, | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         length_hint_doc}, | 
					
						
							|  |  |  |     {NULL,              NULL}           /* sentinel */ | 
					
						
							| 
									
										
										
										
											2005-09-24 21:23:05 +00:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2004-03-10 10:10:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  | static PyObject *rangeiter_new(PyTypeObject *, PyObject *args, PyObject *kw); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-11-29 22:35:39 +00:00
										 |  |  | PyTypeObject PyRangeIter_Type = { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         PyVarObject_HEAD_INIT(&PyType_Type, 0) | 
					
						
							|  |  |  |         "range_iterator",                        /* tp_name */ | 
					
						
							|  |  |  |         sizeof(rangeiterobject),                /* tp_basicsize */ | 
					
						
							|  |  |  |         0,                                      /* tp_itemsize */ | 
					
						
							|  |  |  |         /* methods */ | 
					
						
							|  |  |  |         (destructor)PyObject_Del,               /* tp_dealloc */ | 
					
						
							|  |  |  |         0,                                      /* tp_print */ | 
					
						
							|  |  |  |         0,                                      /* tp_getattr */ | 
					
						
							|  |  |  |         0,                                      /* tp_setattr */ | 
					
						
							|  |  |  |         0,                                      /* tp_reserved */ | 
					
						
							|  |  |  |         0,                                      /* tp_repr */ | 
					
						
							|  |  |  |         0,                                      /* tp_as_number */ | 
					
						
							|  |  |  |         0,                                      /* tp_as_sequence */ | 
					
						
							|  |  |  |         0,                                      /* tp_as_mapping */ | 
					
						
							|  |  |  |         0,                                      /* tp_hash */ | 
					
						
							|  |  |  |         0,                                      /* tp_call */ | 
					
						
							|  |  |  |         0,                                      /* tp_str */ | 
					
						
							|  |  |  |         PyObject_GenericGetAttr,                /* tp_getattro */ | 
					
						
							|  |  |  |         0,                                      /* tp_setattro */ | 
					
						
							|  |  |  |         0,                                      /* tp_as_buffer */ | 
					
						
							|  |  |  |         Py_TPFLAGS_DEFAULT,                     /* tp_flags */ | 
					
						
							|  |  |  |         0,                                      /* tp_doc */ | 
					
						
							|  |  |  |         0,                                      /* tp_traverse */ | 
					
						
							|  |  |  |         0,                                      /* tp_clear */ | 
					
						
							|  |  |  |         0,                                      /* tp_richcompare */ | 
					
						
							|  |  |  |         0,                                      /* tp_weaklistoffset */ | 
					
						
							|  |  |  |         PyObject_SelfIter,                      /* tp_iter */ | 
					
						
							|  |  |  |         (iternextfunc)rangeiter_next,           /* tp_iternext */ | 
					
						
							|  |  |  |         rangeiter_methods,                      /* tp_methods */ | 
					
						
							|  |  |  |         0,                                      /* tp_members */ | 
					
						
							|  |  |  |         0,                                      /* tp_getset */ | 
					
						
							|  |  |  |         0,                                      /* tp_base */ | 
					
						
							|  |  |  |         0,                                      /* tp_dict */ | 
					
						
							|  |  |  |         0,                                      /* tp_descr_get */ | 
					
						
							|  |  |  |         0,                                      /* tp_descr_set */ | 
					
						
							|  |  |  |         0,                                      /* tp_dictoffset */ | 
					
						
							|  |  |  |         0,                                      /* tp_init */ | 
					
						
							|  |  |  |         0,                                      /* tp_alloc */ | 
					
						
							|  |  |  |         rangeiter_new,                          /* tp_new */ | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  | /* Return number of items in range (lo, hi, step).  step != 0
 | 
					
						
							|  |  |  |  * required.  The result always fits in an unsigned long. | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  | static unsigned long | 
					
						
							| 
									
										
										
										
											2010-11-20 23:05:39 +00:00
										 |  |  | get_len_of_range(long lo, long hi, long step) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     /* -------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  |     If step > 0 and lo >= hi, or step < 0 and lo <= hi, the range is empty. | 
					
						
							|  |  |  |     Else for step > 0, if n values are in the range, the last one is | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     lo + (n-1)*step, which must be <= hi-1.  Rearranging, | 
					
						
							|  |  |  |     n <= (hi - lo - 1)/step + 1, so taking the floor of the RHS gives | 
					
						
							|  |  |  |     the proper value.  Since lo < hi in this case, hi-lo-1 >= 0, so | 
					
						
							|  |  |  |     the RHS is non-negative and so truncation is the same as the | 
					
						
							|  |  |  |     floor.  Letting M be the largest positive long, the worst case | 
					
						
							|  |  |  |     for the RHS numerator is hi=M, lo=-M-1, and then | 
					
						
							|  |  |  |     hi-lo-1 = M-(-M-1)-1 = 2*M.  Therefore unsigned long has enough | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  |     precision to compute the RHS exactly.  The analysis for step < 0 | 
					
						
							|  |  |  |     is similar. | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     ---------------------------------------------------------------*/ | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  |     assert(step != 0); | 
					
						
							|  |  |  |     if (step > 0 && lo < hi) | 
					
						
							|  |  |  |         return 1UL + (hi - 1UL - lo) / step; | 
					
						
							|  |  |  |     else if (step < 0 && lo > hi) | 
					
						
							|  |  |  |         return 1UL + (lo - 1UL - hi) / (0UL - step); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         return 0UL; | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  | /* Initialize a rangeiter object.  If the length of the rangeiter object
 | 
					
						
							|  |  |  |    is not representable as a C long, OverflowError is raised. */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  | fast_range_iter(long start, long stop, long step) | 
					
						
							| 
									
										
										
										
											2010-11-20 23:05:39 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-11-29 22:35:39 +00:00
										 |  |  |     rangeiterobject *it = PyObject_New(rangeiterobject, &PyRangeIter_Type); | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  |     unsigned long ulen; | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     if (it == NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     it->start = start; | 
					
						
							|  |  |  |     it->step = step; | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  |     ulen = get_len_of_range(start, stop, step); | 
					
						
							|  |  |  |     if (ulen > (unsigned long)LONG_MAX) { | 
					
						
							| 
									
										
										
										
											2009-11-16 00:34:25 +00:00
										 |  |  |         Py_DECREF(it); | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  |         PyErr_SetString(PyExc_OverflowError, | 
					
						
							|  |  |  |                         "range too large to represent as a range_iterator"); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     it->len = (long)ulen; | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     it->index = 0; | 
					
						
							|  |  |  |     return (PyObject *)it; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2010-11-20 23:05:39 +00:00
										 |  |  | rangeiter_new(PyTypeObject *type, PyObject *args, PyObject *kw) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     long start, stop, step; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!_PyArg_NoKeywords("rangeiter()", kw)) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!PyArg_ParseTuple(args, "lll;rangeiter() requires 3 int arguments", | 
					
						
							|  |  |  |                           &start, &stop, &step)) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |     return fast_range_iter(start, stop, step); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct { | 
					
						
							|  |  |  |     PyObject_HEAD | 
					
						
							|  |  |  |     PyObject *index; | 
					
						
							|  |  |  |     PyObject *start; | 
					
						
							|  |  |  |     PyObject *step; | 
					
						
							|  |  |  |     PyObject *len; | 
					
						
							|  |  |  | } longrangeiterobject; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | longrangeiter_len(longrangeiterobject *r, PyObject *no_args) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return PyNumber_Subtract(r->len, r->index); | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyMethodDef longrangeiter_methods[] = { | 
					
						
							|  |  |  |     {"__length_hint__", (PyCFunction)longrangeiter_len, METH_NOARGS, | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         length_hint_doc}, | 
					
						
							|  |  |  |     {NULL,              NULL}           /* sentinel */ | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							| 
									
										
										
										
											2010-11-20 23:05:39 +00:00
										 |  |  | longrangeiter_dealloc(longrangeiterobject *r) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     Py_XDECREF(r->index); | 
					
						
							| 
									
										
										
										
											2007-05-08 15:18:31 +00:00
										 |  |  |     Py_XDECREF(r->start); | 
					
						
							|  |  |  |     Py_XDECREF(r->step); | 
					
						
							|  |  |  |     Py_XDECREF(r->len); | 
					
						
							| 
									
										
										
										
											2007-11-15 20:52:21 +00:00
										 |  |  |     PyObject_Del(r); | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2010-11-20 23:05:39 +00:00
										 |  |  | longrangeiter_next(longrangeiterobject *r) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     PyObject *one, *product, *new_index, *result; | 
					
						
							|  |  |  |     if (PyObject_RichCompareBool(r->index, r->len, Py_LT) != 1) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     one = PyLong_FromLong(1); | 
					
						
							|  |  |  |     if (!one) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     new_index = PyNumber_Add(r->index, one); | 
					
						
							|  |  |  |     Py_DECREF(one); | 
					
						
							| 
									
										
										
										
											2009-11-16 00:34:25 +00:00
										 |  |  |     if (!new_index) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     product = PyNumber_Multiply(r->index, r->step); | 
					
						
							|  |  |  |     if (!product) { | 
					
						
							|  |  |  |         Py_DECREF(new_index); | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     result = PyNumber_Add(r->start, product); | 
					
						
							|  |  |  |     Py_DECREF(product); | 
					
						
							|  |  |  |     if (result) { | 
					
						
							|  |  |  |         Py_DECREF(r->index); | 
					
						
							|  |  |  |         r->index = new_index; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-11-16 00:34:25 +00:00
										 |  |  |     else { | 
					
						
							|  |  |  |         Py_DECREF(new_index); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-11-29 22:35:39 +00:00
										 |  |  | PyTypeObject PyLongRangeIter_Type = { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         PyVarObject_HEAD_INIT(&PyType_Type, 0) | 
					
						
							|  |  |  |         "longrange_iterator",                   /* tp_name */ | 
					
						
							|  |  |  |         sizeof(longrangeiterobject),            /* tp_basicsize */ | 
					
						
							|  |  |  |         0,                                      /* tp_itemsize */ | 
					
						
							|  |  |  |         /* methods */ | 
					
						
							|  |  |  |         (destructor)longrangeiter_dealloc,      /* tp_dealloc */ | 
					
						
							|  |  |  |         0,                                      /* tp_print */ | 
					
						
							|  |  |  |         0,                                      /* tp_getattr */ | 
					
						
							|  |  |  |         0,                                      /* tp_setattr */ | 
					
						
							|  |  |  |         0,                                      /* tp_reserved */ | 
					
						
							|  |  |  |         0,                                      /* tp_repr */ | 
					
						
							|  |  |  |         0,                                      /* tp_as_number */ | 
					
						
							|  |  |  |         0,                                      /* tp_as_sequence */ | 
					
						
							|  |  |  |         0,                                      /* tp_as_mapping */ | 
					
						
							|  |  |  |         0,                                      /* tp_hash */ | 
					
						
							|  |  |  |         0,                                      /* tp_call */ | 
					
						
							|  |  |  |         0,                                      /* tp_str */ | 
					
						
							|  |  |  |         PyObject_GenericGetAttr,                /* tp_getattro */ | 
					
						
							|  |  |  |         0,                                      /* tp_setattro */ | 
					
						
							|  |  |  |         0,                                      /* tp_as_buffer */ | 
					
						
							|  |  |  |         Py_TPFLAGS_DEFAULT,                     /* tp_flags */ | 
					
						
							|  |  |  |         0,                                      /* tp_doc */ | 
					
						
							|  |  |  |         0,                                      /* tp_traverse */ | 
					
						
							|  |  |  |         0,                                      /* tp_clear */ | 
					
						
							|  |  |  |         0,                                      /* tp_richcompare */ | 
					
						
							|  |  |  |         0,                                      /* tp_weaklistoffset */ | 
					
						
							|  |  |  |         PyObject_SelfIter,                      /* tp_iter */ | 
					
						
							|  |  |  |         (iternextfunc)longrangeiter_next,       /* tp_iternext */ | 
					
						
							|  |  |  |         longrangeiter_methods,                  /* tp_methods */ | 
					
						
							|  |  |  |         0, | 
					
						
							| 
									
										
										
										
											2002-06-05 20:08:48 +00:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2006-04-21 10:40:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2010-11-20 23:05:39 +00:00
										 |  |  | range_iter(PyObject *seq) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     rangeobject *r = (rangeobject *)seq; | 
					
						
							|  |  |  |     longrangeiterobject *it; | 
					
						
							| 
									
										
										
										
											2007-12-20 22:57:23 +00:00
										 |  |  |     long lstart, lstop, lstep; | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  |     PyObject *int_it; | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     assert(PyRange_Check(seq)); | 
					
						
							| 
									
										
										
										
											2007-12-20 22:57:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  |     /* If all three fields and the length convert to long, use the int
 | 
					
						
							|  |  |  |      * version */ | 
					
						
							| 
									
										
										
										
											2007-12-20 22:57:23 +00:00
										 |  |  |     lstart = PyLong_AsLong(r->start); | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  |     if (lstart == -1 && PyErr_Occurred()) { | 
					
						
							|  |  |  |         PyErr_Clear(); | 
					
						
							|  |  |  |         goto long_range; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     lstop = PyLong_AsLong(r->stop); | 
					
						
							|  |  |  |     if (lstop == -1 && PyErr_Occurred()) { | 
					
						
							|  |  |  |         PyErr_Clear(); | 
					
						
							|  |  |  |         goto long_range; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     lstep = PyLong_AsLong(r->step); | 
					
						
							|  |  |  |     if (lstep == -1 && PyErr_Occurred()) { | 
					
						
							|  |  |  |         PyErr_Clear(); | 
					
						
							|  |  |  |         goto long_range; | 
					
						
							| 
									
										
										
										
											2007-12-20 22:57:23 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |     int_it = fast_range_iter(lstart, lstop, lstep); | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  |     if (int_it == NULL && PyErr_ExceptionMatches(PyExc_OverflowError)) { | 
					
						
							|  |  |  |         PyErr_Clear(); | 
					
						
							|  |  |  |         goto long_range; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return (PyObject *)int_it; | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  |   long_range: | 
					
						
							| 
									
										
										
										
											2007-11-29 22:35:39 +00:00
										 |  |  |     it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type); | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     if (it == NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2007-05-08 15:18:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* Do all initialization here, so we can DECREF on failure. */ | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     it->start = r->start; | 
					
						
							| 
									
										
										
										
											2007-05-08 15:18:31 +00:00
										 |  |  |     it->step = r->step; | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |     it->len = r->length; | 
					
						
							| 
									
										
										
										
											2007-05-08 15:18:31 +00:00
										 |  |  |     Py_INCREF(it->start); | 
					
						
							|  |  |  |     Py_INCREF(it->step); | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |     Py_INCREF(it->len); | 
					
						
							| 
									
										
										
										
											2007-05-08 15:18:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     it->index = PyLong_FromLong(0); | 
					
						
							|  |  |  |     if (!it->index) | 
					
						
							|  |  |  |         goto create_failure; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return (PyObject *)it; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | create_failure: | 
					
						
							| 
									
										
										
										
											2007-05-08 15:18:31 +00:00
										 |  |  |     Py_DECREF(it); | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2006-04-21 10:40:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2010-11-20 23:05:39 +00:00
										 |  |  | range_reverse(PyObject *seq) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     rangeobject *range = (rangeobject*) seq; | 
					
						
							|  |  |  |     longrangeiterobject *it; | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |     PyObject *one, *sum, *diff, *product; | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  |     long lstart, lstop, lstep, new_start, new_stop; | 
					
						
							|  |  |  |     unsigned long ulen; | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     assert(PyRange_Check(seq)); | 
					
						
							| 
									
										
										
										
											2007-12-20 22:57:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  |     /* reversed(range(start, stop, step)) can be expressed as
 | 
					
						
							|  |  |  |        range(start+(n-1)*step, start-step, -step), where n is the number of | 
					
						
							|  |  |  |        integers in the range. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        If each of start, stop, step, -step, start-step, and the length | 
					
						
							|  |  |  |        of the iterator is representable as a C long, use the int | 
					
						
							|  |  |  |        version.  This excludes some cases where the reversed range is | 
					
						
							|  |  |  |        representable as a range_iterator, but it's good enough for | 
					
						
							|  |  |  |        common cases and it makes the checks simple. */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-12-20 22:57:23 +00:00
										 |  |  |     lstart = PyLong_AsLong(range->start); | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  |     if (lstart == -1 && PyErr_Occurred()) { | 
					
						
							|  |  |  |         PyErr_Clear(); | 
					
						
							|  |  |  |         goto long_range; | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  |     lstop = PyLong_AsLong(range->stop); | 
					
						
							|  |  |  |     if (lstop == -1 && PyErr_Occurred()) { | 
					
						
							|  |  |  |         PyErr_Clear(); | 
					
						
							|  |  |  |         goto long_range; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     lstep = PyLong_AsLong(range->step); | 
					
						
							|  |  |  |     if (lstep == -1 && PyErr_Occurred()) { | 
					
						
							|  |  |  |         PyErr_Clear(); | 
					
						
							|  |  |  |         goto long_range; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* check for possible overflow of -lstep */ | 
					
						
							|  |  |  |     if (lstep == LONG_MIN) | 
					
						
							|  |  |  |         goto long_range; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* check for overflow of lstart - lstep:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        for lstep > 0, need only check whether lstart - lstep < LONG_MIN. | 
					
						
							|  |  |  |        for lstep < 0, need only check whether lstart - lstep > LONG_MAX | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  |        Rearrange these inequalities as: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            lstart - LONG_MIN < lstep  (lstep > 0) | 
					
						
							|  |  |  |            LONG_MAX - lstart < -lstep  (lstep < 0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        and compute both sides as unsigned longs, to avoid the | 
					
						
							|  |  |  |        possibility of undefined behaviour due to signed overflow. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (lstep > 0) { | 
					
						
							|  |  |  |          if ((unsigned long)lstart - LONG_MIN < (unsigned long)lstep) | 
					
						
							|  |  |  |             goto long_range; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         if (LONG_MAX - (unsigned long)lstart < 0UL - lstep) | 
					
						
							|  |  |  |             goto long_range; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ulen = get_len_of_range(lstart, lstop, lstep); | 
					
						
							|  |  |  |     if (ulen > (unsigned long)LONG_MAX) | 
					
						
							|  |  |  |         goto long_range; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     new_stop = lstart - lstep; | 
					
						
							|  |  |  |     new_start = (long)(new_stop + ulen * lstep); | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |     return fast_range_iter(new_start, new_stop, -lstep); | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | long_range: | 
					
						
							| 
									
										
										
										
											2007-11-29 22:35:39 +00:00
										 |  |  |     it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type); | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     if (it == NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* start + (len - 1) * step */ | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |     it->len = range->length; | 
					
						
							|  |  |  |     Py_INCREF(it->len); | 
					
						
							| 
									
										
										
										
											2009-11-16 00:34:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     one = PyLong_FromLong(1); | 
					
						
							|  |  |  |     if (!one) | 
					
						
							|  |  |  |         goto create_failure; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-03 14:26:13 +00:00
										 |  |  |     diff = PyNumber_Subtract(it->len, one); | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     Py_DECREF(one); | 
					
						
							|  |  |  |     if (!diff) | 
					
						
							|  |  |  |         goto create_failure; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  |     product = PyNumber_Multiply(diff, range->step); | 
					
						
							|  |  |  |     Py_DECREF(diff); | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     if (!product) | 
					
						
							|  |  |  |         goto create_failure; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     sum = PyNumber_Add(range->start, product); | 
					
						
							|  |  |  |     Py_DECREF(product); | 
					
						
							|  |  |  |     it->start = sum; | 
					
						
							|  |  |  |     if (!it->start) | 
					
						
							|  |  |  |         goto create_failure; | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     it->step = PyNumber_Negative(range->step); | 
					
						
							| 
									
										
										
										
											2009-11-16 00:34:25 +00:00
										 |  |  |     if (!it->step) | 
					
						
							| 
									
										
										
										
											2009-11-15 09:57:26 +00:00
										 |  |  |         goto create_failure; | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     it->index = PyLong_FromLong(0); | 
					
						
							| 
									
										
										
										
											2009-11-16 00:34:25 +00:00
										 |  |  |     if (!it->index) | 
					
						
							|  |  |  |         goto create_failure; | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return (PyObject *)it; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | create_failure: | 
					
						
							| 
									
										
										
										
											2009-11-16 00:34:25 +00:00
										 |  |  |     Py_DECREF(it); | 
					
						
							| 
									
										
										
										
											2007-05-07 22:24:25 +00:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2006-04-21 10:40:58 +00:00
										 |  |  | } |