blob: 558130ea8eeb6dbcde3481a2f44247a00ef98fcc [file] [log] [blame]
Guido van Rossum12d12c51993-10-26 17:58:25 +00001/***********************************************************
Guido van Rossumfd71b9e2000-06-30 23:50:40 +00002Copyright (c) 2000, BeOpen.com.
3Copyright (c) 1995-2000, Corporation for National Research Initiatives.
4Copyright (c) 1990-1995, Stichting Mathematisch Centrum.
5All rights reserved.
Guido van Rossum12d12c51993-10-26 17:58:25 +00006
Guido van Rossumfd71b9e2000-06-30 23:50:40 +00007See the file "Misc/COPYRIGHT" for information on usage and
8redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
Guido van Rossum12d12c51993-10-26 17:58:25 +00009******************************************************************/
10
11/* Range object implementation */
12
Guido van Rossumc0b618a1997-05-02 03:12:38 +000013#include "Python.h"
Guido van Rossum12d12c51993-10-26 17:58:25 +000014
15typedef struct {
Guido van Rossumc0b618a1997-05-02 03:12:38 +000016 PyObject_HEAD
Guido van Rossum12d12c51993-10-26 17:58:25 +000017 long start;
18 long step;
19 long len;
Guido van Rossum7d6aa511993-12-21 22:50:31 +000020 int reps;
Guido van Rossum12d12c51993-10-26 17:58:25 +000021} rangeobject;
22
23
Guido van Rossumc0b618a1997-05-02 03:12:38 +000024PyObject *
25PyRange_New(start, len, step, reps)
Guido van Rossum12d12c51993-10-26 17:58:25 +000026 long start, len, step;
Guido van Rossum7d6aa511993-12-21 22:50:31 +000027 int reps;
Guido van Rossum12d12c51993-10-26 17:58:25 +000028{
Guido van Rossumc0b618a1997-05-02 03:12:38 +000029 rangeobject *obj = PyObject_NEW(rangeobject, &PyRange_Type);
Guido van Rossum12d12c51993-10-26 17:58:25 +000030
31 obj->start = start;
32 obj->len = len;
33 obj->step = step;
Guido van Rossum7d6aa511993-12-21 22:50:31 +000034 obj->reps = reps;
Guido van Rossum12d12c51993-10-26 17:58:25 +000035
Guido van Rossumc0b618a1997-05-02 03:12:38 +000036 return (PyObject *) obj;
Guido van Rossum12d12c51993-10-26 17:58:25 +000037}
38
39static void
40range_dealloc(r)
41 rangeobject *r;
42{
Guido van Rossumb18618d2000-05-03 23:44:39 +000043 PyObject_DEL(r);
Guido van Rossum12d12c51993-10-26 17:58:25 +000044}
45
Guido van Rossumc0b618a1997-05-02 03:12:38 +000046static PyObject *
Guido van Rossum12d12c51993-10-26 17:58:25 +000047range_item(r, i)
48 rangeobject *r;
49 int i;
50{
Guido van Rossum7d6aa511993-12-21 22:50:31 +000051 if (i < 0 || i >= r->len * r->reps) {
Guido van Rossumc0b618a1997-05-02 03:12:38 +000052 PyErr_SetString(PyExc_IndexError,
Guido van Rossum5dadf7e1999-01-09 21:40:35 +000053 "xrange object index out of range");
Guido van Rossum12d12c51993-10-26 17:58:25 +000054 return NULL;
55 }
56
Guido van Rossumc0b618a1997-05-02 03:12:38 +000057 return PyInt_FromLong(r->start + (i % r->len) * r->step);
Guido van Rossum12d12c51993-10-26 17:58:25 +000058}
59
60static int
61range_length(r)
62 rangeobject *r;
63{
Guido van Rossum7d6aa511993-12-21 22:50:31 +000064 return r->len * r->reps;
65}
66
67static int
68range_print(r, fp, flags)
69 rangeobject *r;
70 FILE *fp;
71 int flags;
72{
73 int i, j;
74
75 fprintf(fp, "(");
76 for (i = 0; i < r->reps; ++i)
77 for (j = 0; j < r->len; ++j) {
78 if (j > 0 || i > 0)
79 fprintf(fp, ", ");
80
Guido van Rossumda9c2711996-12-05 21:58:58 +000081 fprintf(fp, "%ld", r->start + j * r->step);
Guido van Rossum7d6aa511993-12-21 22:50:31 +000082 }
83
84 if (r->len == 1 && r->reps == 1)
85 fprintf(fp, ",");
86 fprintf(fp, ")");
87 return 0;
Guido van Rossum12d12c51993-10-26 17:58:25 +000088}
89
Guido van Rossumc0b618a1997-05-02 03:12:38 +000090static PyObject *
Guido van Rossum12d12c51993-10-26 17:58:25 +000091range_repr(r)
92 rangeobject *r;
93{
94 char buf[80];
Guido van Rossum03093a21994-09-28 15:51:32 +000095 sprintf(buf, "(xrange(%ld, %ld, %ld) * %d)",
Guido van Rossum7d6aa511993-12-21 22:50:31 +000096 r->start,
97 r->start + r->len * r->step,
98 r->step,
99 r->reps);
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000100 return PyString_FromString(buf);
Guido van Rossum12d12c51993-10-26 17:58:25 +0000101}
102
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000103static PyObject *
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000104range_concat(r, obj)
105 rangeobject *r;
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000106 PyObject *obj;
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000107{
Guido van Rossum5dadf7e1999-01-09 21:40:35 +0000108 PyErr_SetString(PyExc_TypeError, "cannot concatenate xrange objects");
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000109 return NULL;
110}
111
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000112static PyObject *
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000113range_repeat(r, n)
114 rangeobject *r;
115 int n;
116{
117 if (n < 0)
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000118 return (PyObject *) PyRange_New(0, 0, 1, 1);
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000119
120 else if (n == 1) {
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000121 Py_INCREF(r);
122 return (PyObject *) r;
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000123 }
124
125 else
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000126 return (PyObject *) PyRange_New(
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000127 r->start,
128 r->len,
129 r->step,
130 r->reps * n);
131}
132
Guido van Rossum12d12c51993-10-26 17:58:25 +0000133static int
134range_compare(r1, r2)
135 rangeobject *r1, *r2;
136{
137 if (r1->start != r2->start)
138 return r1->start - r2->start;
139
140 else if (r1->step != r2->step)
141 return r1->step - r2->step;
142
143 else if (r1->len != r2->len)
144 return r1->len - r2->len;
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000145
146 else
147 return r1->reps - r2->reps;
Guido van Rossum12d12c51993-10-26 17:58:25 +0000148}
149
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000150static PyObject *
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000151range_slice(r, low, high)
Guido van Rossum12d12c51993-10-26 17:58:25 +0000152 rangeobject *r;
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000153 int low, high;
Guido van Rossum12d12c51993-10-26 17:58:25 +0000154{
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000155 if (r->reps != 1) {
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000156 PyErr_SetString(PyExc_TypeError,
Guido van Rossum5dadf7e1999-01-09 21:40:35 +0000157 "cannot slice a replicated xrange");
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000158 return NULL;
159 }
160 if (low < 0)
161 low = 0;
162 else if (low > r->len)
163 low = r->len;
164 if (high < 0)
165 high = 0;
166 if (high < low)
167 high = low;
168 else if (high > r->len)
169 high = r->len;
170
171 if (low == 0 && high == r->len) {
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000172 Py_INCREF(r);
173 return (PyObject *) r;
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000174 }
175
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000176 return (PyObject *) PyRange_New(
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000177 low * r->step + r->start,
178 high - low,
179 r->step,
180 1);
Guido van Rossum2586bf01993-11-01 16:21:44 +0000181}
Guido van Rossum12d12c51993-10-26 17:58:25 +0000182
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000183static PyObject *
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000184range_tolist(self, args)
185rangeobject *self;
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000186PyObject *args;
Guido van Rossum2586bf01993-11-01 16:21:44 +0000187{
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000188 PyObject *thelist;
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000189 int j;
190 int len = self->len * self->reps;
191
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000192 if (! PyArg_Parse(args, ""))
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000193 return NULL;
194
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000195 if ((thelist = PyList_New(len)) == NULL)
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000196 return NULL;
197
198 for (j = 0; j < len; ++j)
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000199 if ((PyList_SetItem(thelist, j, (PyObject *) PyInt_FromLong(
200 self->start + (j % self->len) * self->step))) < 0)
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000201 return NULL;
202
203 return thelist;
Guido van Rossum2586bf01993-11-01 16:21:44 +0000204}
205
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000206static PyObject *
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000207range_getattr(r, name)
Guido van Rossum2586bf01993-11-01 16:21:44 +0000208 rangeobject *r;
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000209 char *name;
Guido van Rossum2586bf01993-11-01 16:21:44 +0000210{
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000211 static PyMethodDef range_methods[] = {
212 {"tolist", (PyCFunction)range_tolist},
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000213 {NULL, NULL}
214 };
215
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000216 return Py_FindMethod(range_methods, (PyObject *) r, name);
Guido van Rossum12d12c51993-10-26 17:58:25 +0000217}
218
Fred Drake56780252000-06-15 14:50:20 +0000219static int
220range_contains(r, obj)
221 rangeobject * r;
222 PyObject * obj;
223{
224 long num = PyInt_AsLong(obj);
225
226 if (num < 0 && PyErr_Occurred())
227 return -1;
228
229 if (num < r->start || (num - r->start) % r->step)
230 return 0;
231 if (num > (r->start + (r->len * r->step)))
232 return 0;
233 return 1;
234}
235
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000236static PySequenceMethods range_as_sequence = {
Guido van Rossum03093a21994-09-28 15:51:32 +0000237 (inquiry)range_length, /*sq_length*/
238 (binaryfunc)range_concat, /*sq_concat*/
239 (intargfunc)range_repeat, /*sq_repeat*/
240 (intargfunc)range_item, /*sq_item*/
241 (intintargfunc)range_slice, /*sq_slice*/
Guido van Rossum12d12c51993-10-26 17:58:25 +0000242 0, /*sq_ass_item*/
243 0, /*sq_ass_slice*/
Fred Drake56780252000-06-15 14:50:20 +0000244 (objobjproc)range_contains, /*sq_contains*/
Guido van Rossum12d12c51993-10-26 17:58:25 +0000245};
246
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000247PyTypeObject PyRange_Type = {
248 PyObject_HEAD_INIT(&PyType_Type)
Guido van Rossum12d12c51993-10-26 17:58:25 +0000249 0, /* Number of items for varobject */
Guido van Rossum2586bf01993-11-01 16:21:44 +0000250 "xrange", /* Name of this type */
Guido van Rossum12d12c51993-10-26 17:58:25 +0000251 sizeof(rangeobject), /* Basic object size */
252 0, /* Item size for varobject */
Guido van Rossum03093a21994-09-28 15:51:32 +0000253 (destructor)range_dealloc, /*tp_dealloc*/
254 (printfunc)range_print, /*tp_print*/
255 (getattrfunc)range_getattr, /*tp_getattr*/
Guido van Rossum12d12c51993-10-26 17:58:25 +0000256 0, /*tp_setattr*/
Guido van Rossum03093a21994-09-28 15:51:32 +0000257 (cmpfunc)range_compare, /*tp_compare*/
258 (reprfunc)range_repr, /*tp_repr*/
Guido van Rossum12d12c51993-10-26 17:58:25 +0000259 0, /*tp_as_number*/
260 &range_as_sequence, /*tp_as_sequence*/
261 0, /*tp_as_mapping*/
Fred Drake56780252000-06-15 14:50:20 +0000262 0, /*tp_hash*/
263 0, /*tp_call*/
264 0, /*tp_str*/
265 0, /*tp_getattro*/
266 0, /*tp_setattro*/
267 0, /*tp_as_buffer*/
268 Py_TPFLAGS_DEFAULT, /*tp_flags*/
Guido van Rossum12d12c51993-10-26 17:58:25 +0000269};