| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1993-10-26 17:58:25 +00:00
										 |  |  | typedef struct { | 
					
						
							| 
									
										
										
										
											1997-05-02 03:12:38 +00:00
										 |  |  | 	PyObject_HEAD | 
					
						
							| 
									
										
										
										
											1993-10-26 17:58:25 +00:00
										 |  |  | 	long	start; | 
					
						
							|  |  |  | 	long	step; | 
					
						
							|  |  |  | 	long	len; | 
					
						
							|  |  |  | } rangeobject; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-15 12:31:13 +00:00
										 |  |  | /* Return number of items in range (lo, hi, step).  step != 0
 | 
					
						
							|  |  |  |  * required.  The result always fits in an unsigned long. | 
					
						
							| 
									
										
										
										
											2002-06-05 23:12:45 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2009-11-15 12:31:13 +00:00
										 |  |  | static unsigned long | 
					
						
							| 
									
										
										
										
											2002-06-05 23:12:45 +00:00
										 |  |  | get_len_of_range(long lo, long hi, long step) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-11-15 12:31:13 +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 | 
					
						
							|  |  |  |     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 | 
					
						
							|  |  |  |     precision to compute the RHS exactly.  The analysis for step < 0 | 
					
						
							|  |  |  |     is similar. | 
					
						
							|  |  |  |     ---------------------------------------------------------------*/ | 
					
						
							|  |  |  |     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; | 
					
						
							| 
									
										
										
										
											2002-06-05 23:12:45 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | range_new(PyTypeObject *type, PyObject *args, PyObject *kw) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2004-08-08 07:17:39 +00:00
										 |  |  | 	rangeobject *obj; | 
					
						
							| 
									
										
										
										
											2002-06-05 23:12:45 +00:00
										 |  |  | 	long ilow = 0, ihigh = 0, istep = 1; | 
					
						
							| 
									
										
										
										
											2009-11-15 12:31:13 +00:00
										 |  |  | 	unsigned long n; | 
					
						
							| 
									
										
										
										
											2002-06-05 23:12:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-26 06:42:30 +00:00
										 |  |  | 	if (!_PyArg_NoKeywords("xrange()", kw)) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-06-05 23:12:45 +00:00
										 |  |  | 	if (PyTuple_Size(args) <= 1) { | 
					
						
							|  |  |  | 		if (!PyArg_ParseTuple(args, | 
					
						
							|  |  |  | 				"l;xrange() requires 1-3 int arguments", | 
					
						
							|  |  |  | 				&ihigh)) | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		if (!PyArg_ParseTuple(args, | 
					
						
							|  |  |  | 				"ll|l;xrange() requires 1-3 int arguments", | 
					
						
							|  |  |  | 				&ilow, &ihigh, &istep)) | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (istep == 0) { | 
					
						
							|  |  |  | 		PyErr_SetString(PyExc_ValueError, "xrange() arg 3 must not be zero"); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-11-15 12:31:13 +00:00
										 |  |  | 	n = get_len_of_range(ilow, ihigh, istep); | 
					
						
							|  |  |  | 	if (n > (unsigned long)LONG_MAX || (long)n > PY_SSIZE_T_MAX) { | 
					
						
							| 
									
										
										
										
											2002-06-05 23:12:45 +00:00
										 |  |  | 		PyErr_SetString(PyExc_OverflowError, | 
					
						
							|  |  |  | 				"xrange() result has too many items"); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2004-08-08 07:17:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	obj = PyObject_New(rangeobject, &PyRange_Type); | 
					
						
							|  |  |  | 	if (obj == NULL) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	obj->start = ilow; | 
					
						
							| 
									
										
										
										
											2009-11-15 12:31:13 +00:00
										 |  |  | 	obj->len   = (long)n; | 
					
						
							| 
									
										
										
										
											2004-08-08 07:17:39 +00:00
										 |  |  | 	obj->step  = istep; | 
					
						
							|  |  |  | 	return (PyObject *) obj; | 
					
						
							| 
									
										
										
										
											2002-06-05 23:12:45 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-06-13 20:33:02 +00:00
										 |  |  | PyDoc_STRVAR(range_doc, | 
					
						
							| 
									
										
										
										
											2002-06-05 23:12:45 +00:00
										 |  |  | "xrange([start,] stop[, step]) -> xrange object\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | Like range(), but instead of returning a list, returns an object that\n\ | 
					
						
							| 
									
										
										
										
											2002-12-11 07:14:03 +00:00
										 |  |  | generates the numbers in the range on demand.  For looping, this is \n\ | 
					
						
							|  |  |  | slightly faster than range() and more memory efficient."); | 
					
						
							| 
									
										
										
										
											2002-06-05 23:12:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-05-02 03:12:38 +00:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | range_item(rangeobject *r, Py_ssize_t i) | 
					
						
							| 
									
										
										
										
											1993-10-26 17:58:25 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2002-05-02 19:56:55 +00:00
										 |  |  | 	if (i < 0 || i >= r->len) { | 
					
						
							|  |  |  | 		PyErr_SetString(PyExc_IndexError, | 
					
						
							| 
									
										
										
										
											1999-01-09 21:40:35 +00:00
										 |  |  | 				"xrange object index out of range"); | 
					
						
							| 
									
										
										
										
											2002-05-02 19:56:55 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-11-15 12:31:13 +00:00
										 |  |  | 	/* do calculation entirely using unsigned longs, to avoid
 | 
					
						
							|  |  |  | 	   undefined behaviour due to signed overflow. */ | 
					
						
							|  |  |  | 	return PyInt_FromLong((long)(r->start + (unsigned long)i * r->step)); | 
					
						
							| 
									
										
										
										
											1993-10-26 17:58:25 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | static Py_ssize_t | 
					
						
							| 
									
										
										
										
											2000-07-09 06:21:27 +00:00
										 |  |  | range_length(rangeobject *r) | 
					
						
							| 
									
										
										
										
											1993-10-26 17:58:25 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	return (Py_ssize_t)(r->len); | 
					
						
							| 
									
										
										
										
											1993-12-21 22:50:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-05-02 03:12:38 +00:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2000-07-09 06:21:27 +00:00
										 |  |  | range_repr(rangeobject *r) | 
					
						
							| 
									
										
										
										
											1993-10-26 17:58:25 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2001-08-24 18:34:26 +00:00
										 |  |  | 	PyObject *rtn; | 
					
						
							| 
									
										
										
										
											2004-08-08 06:29:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-08-04 03:05:40 +00:00
										 |  |  | 	if (r->start == 0 && r->step == 1) | 
					
						
							| 
									
										
										
										
											2008-06-09 04:58:54 +00:00
										 |  |  | 		rtn = PyString_FromFormat("xrange(%ld)", | 
					
						
							| 
									
										
										
										
											2001-08-24 18:34:26 +00:00
										 |  |  | 					  r->start + r->len * r->step); | 
					
						
							| 
									
										
										
										
											2000-08-04 03:05:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	else if (r->step == 1) | 
					
						
							| 
									
										
										
										
											2008-06-09 04:58:54 +00:00
										 |  |  | 		rtn = PyString_FromFormat("xrange(%ld, %ld)", | 
					
						
							| 
									
										
										
										
											2001-08-24 18:34:26 +00:00
										 |  |  | 					  r->start, | 
					
						
							|  |  |  | 					  r->start + r->len * r->step); | 
					
						
							| 
									
										
										
										
											2000-08-04 03:05:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	else | 
					
						
							| 
									
										
										
										
											2008-06-09 04:58:54 +00:00
										 |  |  | 		rtn = PyString_FromFormat("xrange(%ld, %ld, %ld)", | 
					
						
							| 
									
										
										
										
											2001-08-24 18:34:26 +00:00
										 |  |  | 					  r->start, | 
					
						
							|  |  |  | 					  r->start + r->len * r->step, | 
					
						
							|  |  |  | 					  r->step); | 
					
						
							|  |  |  | 	return rtn; | 
					
						
							| 
									
										
										
										
											2001-07-09 12:30:54 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-10 03:34:53 +00:00
										 |  |  | /* Pickling support */ | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2008-06-10 04:01:23 +00:00
										 |  |  | range_reduce(rangeobject *r, PyObject *args) | 
					
						
							| 
									
										
										
										
											2008-06-10 03:34:53 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-06-10 04:01:23 +00:00
										 |  |  | 	return Py_BuildValue("(O(iii))", Py_TYPE(r), | 
					
						
							| 
									
										
										
										
											2008-06-10 03:34:53 +00:00
										 |  |  | 			     r->start, | 
					
						
							|  |  |  | 			     r->start + r->len * r->step, | 
					
						
							|  |  |  | 			     r->step); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-05-02 03:12:38 +00:00
										 |  |  | static PySequenceMethods range_as_sequence = { | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	(lenfunc)range_length,	/* sq_length */ | 
					
						
							| 
									
										
										
										
											2002-05-02 19:56:55 +00:00
										 |  |  | 	0,			/* sq_concat */ | 
					
						
							|  |  |  | 	0,			/* sq_repeat */ | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | 	(ssizeargfunc)range_item, /* sq_item */ | 
					
						
							| 
									
										
										
										
											2002-05-02 19:56:55 +00:00
										 |  |  | 	0,			/* sq_slice */ | 
					
						
							| 
									
										
										
										
											1993-10-26 17:58:25 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyMethodDef range_methods[] = { | 
					
						
							|  |  |  | 	{"__reversed__",	(PyCFunction)range_reverse, METH_NOARGS, reverse_doc}, | 
					
						
							| 
									
										
										
										
											2008-06-10 04:01:23 +00:00
										 |  |  | 	{"__reduce__",		(PyCFunction)range_reduce, METH_VARARGS}, | 
					
						
							| 
									
										
										
										
											2003-11-06 14:06:48 +00:00
										 |  |  |  	{NULL,		NULL}		/* sentinel */ | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2002-06-05 20:08:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-05-02 03:12:38 +00:00
										 |  |  | PyTypeObject PyRange_Type = { | 
					
						
							|  |  |  | 	PyObject_HEAD_INIT(&PyType_Type) | 
					
						
							| 
									
										
										
										
											2006-03-30 11:57:00 +00:00
										 |  |  | 	0,			/* Number of items for varobject */ | 
					
						
							|  |  |  | 	"xrange",		/* Name of this type */ | 
					
						
							|  |  |  | 	sizeof(rangeobject),	/* Basic object size */ | 
					
						
							|  |  |  | 	0,			/* Item size for varobject */ | 
					
						
							|  |  |  | 	(destructor)PyObject_Del, /* tp_dealloc */ | 
					
						
							|  |  |  | 	0,			/* tp_print */ | 
					
						
							|  |  |  | 	0,			/* tp_getattr */ | 
					
						
							|  |  |  | 	0,			/* tp_setattr */ | 
					
						
							|  |  |  | 	0,			/* tp_compare */ | 
					
						
							|  |  |  | 	(reprfunc)range_repr,	/* tp_repr */ | 
					
						
							|  |  |  | 	0,			/* tp_as_number */ | 
					
						
							|  |  |  | 	&range_as_sequence,	/* 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 */ | 
					
						
							|  |  |  | 	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
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*********************** Xrange Iterator **************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct { | 
					
						
							|  |  |  | 	PyObject_HEAD | 
					
						
							|  |  |  | 	long	index; | 
					
						
							|  |  |  | 	long	start; | 
					
						
							|  |  |  | 	long	step; | 
					
						
							|  |  |  | 	long	len; | 
					
						
							|  |  |  | } rangeiterobject; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | rangeiter_next(rangeiterobject *r) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2004-08-08 06:29:10 +00:00
										 |  |  | 	if (r->index < r->len) | 
					
						
							| 
									
										
										
										
											2002-06-05 20:08:48 +00:00
										 |  |  | 		return PyInt_FromLong(r->start + (r->index++) * r->step); | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-09-24 21:23:05 +00:00
										 |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2004-03-10 10:10:42 +00:00
										 |  |  | rangeiter_len(rangeiterobject *r) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-09-24 21:23:05 +00:00
										 |  |  | 	return PyInt_FromLong(r->len - r->index); | 
					
						
							| 
									
										
										
										
											2004-03-10 10:10:42 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-11 21:32:43 +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[] = { | 
					
						
							| 
									
										
										
										
											2006-02-11 21:32:43 +00:00
										 |  |  | 	{"__length_hint__", (PyCFunction)rangeiter_len, METH_NOARGS, length_hint_doc}, | 
					
						
							| 
									
										
										
										
											2005-09-24 21:23:05 +00:00
										 |  |  |  	{NULL,		NULL}		/* sentinel */ | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2004-03-10 10:10:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-06-06 14:58:21 +00:00
										 |  |  | static PyTypeObject Pyrangeiter_Type = { | 
					
						
							| 
									
										
										
										
											2002-06-05 20:08:48 +00:00
										 |  |  | 	PyObject_HEAD_INIT(&PyType_Type) | 
					
						
							|  |  |  | 	0,                                      /* ob_size */ | 
					
						
							| 
									
										
										
										
											2002-06-06 14:58:21 +00:00
										 |  |  | 	"rangeiterator",                        /* tp_name */ | 
					
						
							|  |  |  | 	sizeof(rangeiterobject),                /* tp_basicsize */ | 
					
						
							| 
									
										
										
										
											2002-06-05 20:08:48 +00:00
										 |  |  | 	0,                                      /* tp_itemsize */ | 
					
						
							|  |  |  | 	/* methods */ | 
					
						
							|  |  |  | 	(destructor)PyObject_Del,		/* tp_dealloc */ | 
					
						
							|  |  |  | 	0,                                      /* tp_print */ | 
					
						
							|  |  |  | 	0,                                      /* tp_getattr */ | 
					
						
							|  |  |  | 	0,                                      /* tp_setattr */ | 
					
						
							|  |  |  | 	0,                                      /* tp_compare */ | 
					
						
							|  |  |  | 	0,                                      /* tp_repr */ | 
					
						
							|  |  |  | 	0,                                      /* tp_as_number */ | 
					
						
							| 
									
										
										
										
											2005-09-24 21:23:05 +00:00
										 |  |  | 	0,					/* tp_as_sequence */ | 
					
						
							| 
									
										
										
										
											2002-06-05 20:08:48 +00:00
										 |  |  | 	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 */ | 
					
						
							| 
									
										
										
										
											2003-03-17 19:46:11 +00:00
										 |  |  | 	PyObject_SelfIter,			/* tp_iter */ | 
					
						
							| 
									
										
										
										
											2002-06-05 20:08:48 +00:00
										 |  |  | 	(iternextfunc)rangeiter_next,		/* tp_iternext */ | 
					
						
							| 
									
										
										
										
											2005-09-24 21:23:05 +00:00
										 |  |  | 	rangeiter_methods,			/* tp_methods */ | 
					
						
							|  |  |  | 	0, | 
					
						
							| 
									
										
										
										
											2002-06-05 20:08:48 +00:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2006-04-11 09:04:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | range_iter(PyObject *seq) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	rangeiterobject *it; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!PyRange_Check(seq)) { | 
					
						
							|  |  |  | 		PyErr_BadInternalCall(); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	it = PyObject_New(rangeiterobject, &Pyrangeiter_Type); | 
					
						
							|  |  |  | 	if (it == NULL) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	it->index = 0; | 
					
						
							|  |  |  | 	it->start = ((rangeobject *)seq)->start; | 
					
						
							|  |  |  | 	it->step = ((rangeobject *)seq)->step; | 
					
						
							|  |  |  | 	it->len = ((rangeobject *)seq)->len; | 
					
						
							|  |  |  | 	return (PyObject *)it; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | range_reverse(PyObject *seq) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	rangeiterobject *it; | 
					
						
							|  |  |  | 	long start, step, len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!PyRange_Check(seq)) { | 
					
						
							|  |  |  | 		PyErr_BadInternalCall(); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	it = PyObject_New(rangeiterobject, &Pyrangeiter_Type); | 
					
						
							|  |  |  | 	if (it == NULL) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	start = ((rangeobject *)seq)->start; | 
					
						
							|  |  |  | 	step = ((rangeobject *)seq)->step; | 
					
						
							|  |  |  | 	len = ((rangeobject *)seq)->len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	it->index = 0; | 
					
						
							|  |  |  | 	it->len = len; | 
					
						
							| 
									
										
										
										
											2009-11-15 12:31:13 +00:00
										 |  |  | 	/* the casts below guard against signed overflow by turning it
 | 
					
						
							|  |  |  | 	   into unsigned overflow instead.  The correctness of this | 
					
						
							|  |  |  | 	   code still depends on conversion from unsigned long to long | 
					
						
							|  |  |  | 	   wrapping modulo ULONG_MAX+1, which isn't guaranteed (see | 
					
						
							|  |  |  | 	   C99 6.3.1.3p3) but seems to hold in practice for all | 
					
						
							|  |  |  | 	   platforms we're likely to meet. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	   If step == LONG_MIN then we still end up with LONG_MIN | 
					
						
							|  |  |  | 	   after negation; but this works out, since we've still got | 
					
						
							|  |  |  | 	   the correct value modulo ULONG_MAX+1, and the range_item | 
					
						
							|  |  |  | 	   calculation is also done modulo ULONG_MAX+1. | 
					
						
							|  |  |  | 	*/ | 
					
						
							|  |  |  | 	it->start = (long)(start + (unsigned long)(len-1) * step); | 
					
						
							| 
									
										
										
										
											2009-11-16 17:33:25 +00:00
										 |  |  | 	it->step = (long)(0UL-step); | 
					
						
							| 
									
										
										
										
											2006-04-11 09:04:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return (PyObject *)it; | 
					
						
							|  |  |  | } |