2 /* Range object implementation */
5 #include "structmember.h"
18 PyRange_New(long start
, long len
, long step
, int reps
)
20 rangeobject
*obj
= PyObject_NEW(rangeobject
, &PyRange_Type
);
27 return (PyObject
*) obj
;
31 range_dealloc(rangeobject
*r
)
37 range_item(rangeobject
*r
, int i
)
39 if (i
< 0 || i
>= r
->len
* r
->reps
) {
40 PyErr_SetString(PyExc_IndexError
,
41 "xrange object index out of range");
45 return PyInt_FromLong(r
->start
+ (i
% r
->len
) * r
->step
);
49 range_length(rangeobject
*r
)
51 return r
->len
* r
->reps
;
55 range_repr(rangeobject
*r
)
57 /* buffers must be big enough to hold 3 longs + an int +
58 * a bit of "(xrange(...) * ...)" text.
63 if (r
->start
== 0 && r
->step
== 1)
64 sprintf(buf1
, "xrange(%ld)", r
->start
+ r
->len
* r
->step
);
66 else if (r
->step
== 1)
67 sprintf(buf1
, "xrange(%ld, %ld)",
69 r
->start
+ r
->len
* r
->step
);
72 sprintf(buf1
, "xrange(%ld, %ld, %ld)",
74 r
->start
+ r
->len
* r
->step
,
78 sprintf(buf2
, "(%s * %d)", buf1
, r
->reps
);
80 return PyString_FromString(r
->reps
== 1 ? buf1
: buf2
);
84 range_concat(rangeobject
*r
, PyObject
*obj
)
86 PyErr_SetString(PyExc_TypeError
, "cannot concatenate xrange objects");
91 range_repeat(rangeobject
*r
, int n
)
94 return (PyObject
*) PyRange_New(0, 0, 1, 1);
98 return (PyObject
*) r
;
102 return (PyObject
*) PyRange_New(
110 range_compare(rangeobject
*r1
, rangeobject
*r2
)
112 if (r1
->start
!= r2
->start
)
113 return r1
->start
- r2
->start
;
115 else if (r1
->step
!= r2
->step
)
116 return r1
->step
- r2
->step
;
118 else if (r1
->len
!= r2
->len
)
119 return r1
->len
- r2
->len
;
122 return r1
->reps
- r2
->reps
;
126 range_slice(rangeobject
*r
, int low
, int high
)
129 PyErr_SetString(PyExc_TypeError
,
130 "cannot slice a replicated xrange");
135 else if (low
> r
->len
)
141 else if (high
> r
->len
)
144 if (low
== 0 && high
== r
->len
) {
146 return (PyObject
*) r
;
149 return (PyObject
*) PyRange_New(
150 low
* r
->step
+ r
->start
,
157 range_tolist(rangeobject
*self
, PyObject
*args
)
161 int len
= self
->len
* self
->reps
;
163 if (! PyArg_ParseTuple(args
, ":tolist"))
166 if ((thelist
= PyList_New(len
)) == NULL
)
169 for (j
= 0; j
< len
; ++j
)
170 if ((PyList_SetItem(thelist
, j
, (PyObject
*) PyInt_FromLong(
171 self
->start
+ (j
% self
->len
) * self
->step
))) < 0)
178 range_getattr(rangeobject
*r
, char *name
)
180 static PyMethodDef range_methods
[] = {
181 {"tolist", (PyCFunction
)range_tolist
, METH_VARARGS
,
183 "Return a list object with the same values."},
187 return Py_FindMethod(range_methods
, (PyObject
*) r
, name
);
191 range_contains(rangeobject
*r
, PyObject
*obj
)
193 long num
= PyInt_AsLong(obj
);
195 if (num
< 0 && PyErr_Occurred())
199 if ((num
< r
->start
) || ((num
- r
->start
) % r
->step
))
201 if (num
>= (r
->start
+ (r
->len
* r
->step
)))
205 if ((num
> r
->start
) || ((num
- r
->start
) % r
->step
))
207 if (num
<= (r
->start
+ (r
->len
* r
->step
)))
213 static PySequenceMethods range_as_sequence
= {
214 (inquiry
)range_length
, /*sq_length*/
215 (binaryfunc
)range_concat
, /*sq_concat*/
216 (intargfunc
)range_repeat
, /*sq_repeat*/
217 (intargfunc
)range_item
, /*sq_item*/
218 (intintargfunc
)range_slice
, /*sq_slice*/
221 (objobjproc
)range_contains
, /*sq_contains*/
224 PyTypeObject PyRange_Type
= {
225 PyObject_HEAD_INIT(&PyType_Type
)
226 0, /* Number of items for varobject */
227 "xrange", /* Name of this type */
228 sizeof(rangeobject
), /* Basic object size */
229 0, /* Item size for varobject */
230 (destructor
)range_dealloc
, /*tp_dealloc*/
232 (getattrfunc
)range_getattr
, /*tp_getattr*/
234 (cmpfunc
)range_compare
, /*tp_compare*/
235 (reprfunc
)range_repr
, /*tp_repr*/
237 &range_as_sequence
, /*tp_as_sequence*/
245 Py_TPFLAGS_DEFAULT
, /*tp_flags*/