2 /* Range object implementation */
5 #include "structmember.h"
18 long_mul(long i
, long j
, long *kk
)
24 if ((a
= PyInt_FromLong(i
)) == NULL
)
27 if ((b
= PyInt_FromLong(j
)) == NULL
)
30 c
= PyNumber_Multiply(a
, b
);
38 *kk
= PyInt_AS_LONG(c
);
42 PyErr_SetString(PyExc_OverflowError
,
43 "integer multiplication");
51 PyRange_New(long start
, long len
, long step
, int reps
)
54 rangeobject
*obj
= PyObject_NEW(rangeobject
, &PyRange_Type
);
59 if (len
== 0 || reps
<= 0) {
67 long last
= start
+ (len
- 1) * step
;
69 (last
> (PyInt_GetMax() - step
))
70 :(last
< (-1 - PyInt_GetMax() - step
))) {
71 PyErr_SetString(PyExc_OverflowError
,
75 if (! long_mul(len
, (long) reps
, &totlen
)) {
76 if(!PyErr_ExceptionMatches(PyExc_OverflowError
))
89 return (PyObject
*) obj
;
93 range_dealloc(rangeobject
*r
)
99 range_item(rangeobject
*r
, int i
)
101 if (i
< 0 || i
>= r
->totlen
)
103 PyErr_SetString(PyExc_IndexError
,
104 "xrange object index out of range");
108 return PyInt_FromLong(r
->start
+ (i
% r
->len
) * r
->step
);
112 range_length(rangeobject
*r
)
115 PyErr_SetString(PyExc_OverflowError
,
116 "xrange object has too many items");
121 range_repr(rangeobject
*r
)
123 /* buffers must be big enough to hold 3 longs + an int +
124 * a bit of "(xrange(...) * ...)" text.
129 if (r
->start
== 0 && r
->step
== 1)
130 sprintf(buf1
, "xrange(%ld)", r
->start
+ r
->len
* r
->step
);
132 else if (r
->step
== 1)
133 sprintf(buf1
, "xrange(%ld, %ld)",
135 r
->start
+ r
->len
* r
->step
);
138 sprintf(buf1
, "xrange(%ld, %ld, %ld)",
140 r
->start
+ r
->len
* r
->step
,
144 sprintf(buf2
, "(%s * %d)", buf1
, r
->reps
);
146 return PyString_FromString(r
->reps
== 1 ? buf1
: buf2
);
150 range_concat(rangeobject
*r
, PyObject
*obj
)
152 PyErr_SetString(PyExc_TypeError
, "cannot concatenate xrange objects");
157 range_repeat(rangeobject
*r
, int n
)
162 return (PyObject
*) PyRange_New(0, 0, 1, 1);
166 return (PyObject
*) r
;
169 else if (! long_mul((long) r
->reps
, (long) n
, &lreps
))
173 return (PyObject
*) PyRange_New(
181 range_compare(rangeobject
*r1
, rangeobject
*r2
)
183 if (r1
->start
!= r2
->start
)
184 return r1
->start
- r2
->start
;
186 else if (r1
->step
!= r2
->step
)
187 return r1
->step
- r2
->step
;
189 else if (r1
->len
!= r2
->len
)
190 return r1
->len
- r2
->len
;
193 return r1
->reps
- r2
->reps
;
197 range_slice(rangeobject
*r
, int low
, int high
)
200 PyErr_SetString(PyExc_TypeError
,
201 "cannot slice a replicated xrange");
206 else if (low
> r
->len
)
212 else if (high
> r
->len
)
215 if (low
== 0 && high
== r
->len
) {
217 return (PyObject
*) r
;
220 return (PyObject
*) PyRange_New(
221 low
* r
->step
+ r
->start
,
228 range_tolist(rangeobject
*self
, PyObject
*args
)
233 if (! PyArg_ParseTuple(args
, ":tolist"))
236 if (self
->totlen
== -1)
237 return PyErr_NoMemory();
239 if ((thelist
= PyList_New(self
->totlen
)) == NULL
)
242 for (j
= 0; j
< self
->totlen
; ++j
)
243 if ((PyList_SetItem(thelist
, j
, (PyObject
*) PyInt_FromLong(
244 self
->start
+ (j
% self
->len
) * self
->step
))) < 0)
251 range_getattr(rangeobject
*r
, char *name
)
255 static PyMethodDef range_methods
[] = {
256 {"tolist", (PyCFunction
)range_tolist
, METH_VARARGS
,
258 "Return a list object with the same values."},
261 static struct memberlist range_members
[] = {
262 {"step", T_LONG
, offsetof(rangeobject
, step
), RO
},
263 {"start", T_LONG
, offsetof(rangeobject
, start
), RO
},
264 {"stop", T_LONG
, 0, RO
},
268 result
= Py_FindMethod(range_methods
, (PyObject
*) r
, name
);
269 if (result
== NULL
) {
271 if (strcmp("stop", name
) == 0)
272 result
= PyInt_FromLong(r
->start
+ (r
->len
* r
->step
));
274 result
= PyMember_Get((char *)r
, range_members
, name
);
280 range_contains(rangeobject
*r
, PyObject
*obj
)
282 long num
= PyInt_AsLong(obj
);
284 if (num
< 0 && PyErr_Occurred())
288 if ((num
< r
->start
) || ((num
- r
->start
) % r
->step
))
290 if (num
>= (r
->start
+ (r
->len
* r
->step
)))
294 if ((num
> r
->start
) || ((num
- r
->start
) % r
->step
))
296 if (num
<= (r
->start
+ (r
->len
* r
->step
)))
302 static PySequenceMethods range_as_sequence
= {
303 (inquiry
)range_length
, /*sq_length*/
304 (binaryfunc
)range_concat
, /*sq_concat*/
305 (intargfunc
)range_repeat
, /*sq_repeat*/
306 (intargfunc
)range_item
, /*sq_item*/
307 (intintargfunc
)range_slice
, /*sq_slice*/
310 (objobjproc
)range_contains
, /*sq_contains*/
313 PyTypeObject PyRange_Type
= {
314 PyObject_HEAD_INIT(&PyType_Type
)
315 0, /* Number of items for varobject */
316 "xrange", /* Name of this type */
317 sizeof(rangeobject
), /* Basic object size */
318 0, /* Item size for varobject */
319 (destructor
)range_dealloc
, /*tp_dealloc*/
321 (getattrfunc
)range_getattr
, /*tp_getattr*/
323 (cmpfunc
)range_compare
, /*tp_compare*/
324 (reprfunc
)range_repr
, /*tp_repr*/
326 &range_as_sequence
, /*tp_as_sequence*/
334 Py_TPFLAGS_DEFAULT
, /*tp_flags*/