blob: 0bf643f324a4ddee37badab4d300b10da91fc44a [file] [log] [blame]
Guido van Rossum12d12c51993-10-26 17:58:25 +00001/***********************************************************
Guido van Rossum6610ad91995-01-04 19:07:38 +00002Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
Guido van Rossum12d12c51993-10-26 17:58:25 +00004
5 All Rights Reserved
6
Guido van Rossumd266eb41996-10-25 14:44:06 +00007Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
Guido van Rossum12d12c51993-10-26 17:58:25 +00009provided that the above copyright notice appear in all copies and that
Guido van Rossumd266eb41996-10-25 14:44:06 +000010both that copyright notice and this permission notice appear in
Guido van Rossum12d12c51993-10-26 17:58:25 +000011supporting documentation, and that the names of Stichting Mathematisch
Guido van Rossumd266eb41996-10-25 14:44:06 +000012Centrum or CWI or Corporation for National Research Initiatives or
13CNRI not be used in advertising or publicity pertaining to
14distribution of the software without specific, written prior
15permission.
Guido van Rossum12d12c51993-10-26 17:58:25 +000016
Guido van Rossumd266eb41996-10-25 14:44:06 +000017While CWI is the initial source for this software, a modified version
18is made available by the Corporation for National Research Initiatives
19(CNRI) at the Internet address ftp://ftp.python.org.
20
21STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28PERFORMANCE OF THIS SOFTWARE.
Guido van Rossum12d12c51993-10-26 17:58:25 +000029
30******************************************************************/
31
32/* Range object implementation */
33
Guido van Rossumc0b618a1997-05-02 03:12:38 +000034#include "Python.h"
Guido van Rossum12d12c51993-10-26 17:58:25 +000035
36typedef struct {
Guido van Rossumc0b618a1997-05-02 03:12:38 +000037 PyObject_HEAD
Guido van Rossum12d12c51993-10-26 17:58:25 +000038 long start;
39 long step;
40 long len;
Guido van Rossum7d6aa511993-12-21 22:50:31 +000041 int reps;
Guido van Rossum12d12c51993-10-26 17:58:25 +000042} rangeobject;
43
44
Guido van Rossumc0b618a1997-05-02 03:12:38 +000045PyObject *
46PyRange_New(start, len, step, reps)
Guido van Rossum12d12c51993-10-26 17:58:25 +000047 long start, len, step;
Guido van Rossum7d6aa511993-12-21 22:50:31 +000048 int reps;
Guido van Rossum12d12c51993-10-26 17:58:25 +000049{
Guido van Rossumc0b618a1997-05-02 03:12:38 +000050 rangeobject *obj = PyObject_NEW(rangeobject, &PyRange_Type);
Guido van Rossum12d12c51993-10-26 17:58:25 +000051
52 obj->start = start;
53 obj->len = len;
54 obj->step = step;
Guido van Rossum7d6aa511993-12-21 22:50:31 +000055 obj->reps = reps;
Guido van Rossum12d12c51993-10-26 17:58:25 +000056
Guido van Rossumc0b618a1997-05-02 03:12:38 +000057 return (PyObject *) obj;
Guido van Rossum12d12c51993-10-26 17:58:25 +000058}
59
60static void
61range_dealloc(r)
62 rangeobject *r;
63{
Guido van Rossumc0b618a1997-05-02 03:12:38 +000064 PyMem_DEL(r);
Guido van Rossum12d12c51993-10-26 17:58:25 +000065}
66
Guido van Rossumc0b618a1997-05-02 03:12:38 +000067static PyObject *
Guido van Rossum12d12c51993-10-26 17:58:25 +000068range_item(r, i)
69 rangeobject *r;
70 int i;
71{
Guido van Rossum7d6aa511993-12-21 22:50:31 +000072 if (i < 0 || i >= r->len * r->reps) {
Guido van Rossumc0b618a1997-05-02 03:12:38 +000073 PyErr_SetString(PyExc_IndexError,
74 "range object index out of range");
Guido van Rossum12d12c51993-10-26 17:58:25 +000075 return NULL;
76 }
77
Guido van Rossumc0b618a1997-05-02 03:12:38 +000078 return PyInt_FromLong(r->start + (i % r->len) * r->step);
Guido van Rossum12d12c51993-10-26 17:58:25 +000079}
80
81static int
82range_length(r)
83 rangeobject *r;
84{
Guido van Rossum7d6aa511993-12-21 22:50:31 +000085 return r->len * r->reps;
86}
87
88static int
89range_print(r, fp, flags)
90 rangeobject *r;
91 FILE *fp;
92 int flags;
93{
94 int i, j;
95
96 fprintf(fp, "(");
97 for (i = 0; i < r->reps; ++i)
98 for (j = 0; j < r->len; ++j) {
99 if (j > 0 || i > 0)
100 fprintf(fp, ", ");
101
Guido van Rossumda9c2711996-12-05 21:58:58 +0000102 fprintf(fp, "%ld", r->start + j * r->step);
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000103 }
104
105 if (r->len == 1 && r->reps == 1)
106 fprintf(fp, ",");
107 fprintf(fp, ")");
108 return 0;
Guido van Rossum12d12c51993-10-26 17:58:25 +0000109}
110
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000111static PyObject *
Guido van Rossum12d12c51993-10-26 17:58:25 +0000112range_repr(r)
113 rangeobject *r;
114{
115 char buf[80];
Guido van Rossum03093a21994-09-28 15:51:32 +0000116 sprintf(buf, "(xrange(%ld, %ld, %ld) * %d)",
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000117 r->start,
118 r->start + r->len * r->step,
119 r->step,
120 r->reps);
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000121 return PyString_FromString(buf);
Guido van Rossum12d12c51993-10-26 17:58:25 +0000122}
123
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000124static PyObject *
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000125range_concat(r, obj)
126 rangeobject *r;
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000127 PyObject *obj;
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000128{
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000129 PyErr_SetString(PyExc_TypeError, "cannot concatenate range objects");
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000130 return NULL;
131}
132
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000133static PyObject *
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000134range_repeat(r, n)
135 rangeobject *r;
136 int n;
137{
138 if (n < 0)
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000139 return (PyObject *) PyRange_New(0, 0, 1, 1);
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000140
141 else if (n == 1) {
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000142 Py_INCREF(r);
143 return (PyObject *) r;
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000144 }
145
146 else
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000147 return (PyObject *) PyRange_New(
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000148 r->start,
149 r->len,
150 r->step,
151 r->reps * n);
152}
153
Guido van Rossum12d12c51993-10-26 17:58:25 +0000154static int
155range_compare(r1, r2)
156 rangeobject *r1, *r2;
157{
158 if (r1->start != r2->start)
159 return r1->start - r2->start;
160
161 else if (r1->step != r2->step)
162 return r1->step - r2->step;
163
164 else if (r1->len != r2->len)
165 return r1->len - r2->len;
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000166
167 else
168 return r1->reps - r2->reps;
Guido van Rossum12d12c51993-10-26 17:58:25 +0000169}
170
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000171static PyObject *
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000172range_slice(r, low, high)
Guido van Rossum12d12c51993-10-26 17:58:25 +0000173 rangeobject *r;
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000174 int low, high;
Guido van Rossum12d12c51993-10-26 17:58:25 +0000175{
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000176 if (r->reps != 1) {
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000177 PyErr_SetString(PyExc_TypeError,
178 "cannot slice a replicated range");
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000179 return NULL;
180 }
181 if (low < 0)
182 low = 0;
183 else if (low > r->len)
184 low = r->len;
185 if (high < 0)
186 high = 0;
187 if (high < low)
188 high = low;
189 else if (high > r->len)
190 high = r->len;
191
192 if (low == 0 && high == r->len) {
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000193 Py_INCREF(r);
194 return (PyObject *) r;
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000195 }
196
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000197 return (PyObject *) PyRange_New(
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000198 low * r->step + r->start,
199 high - low,
200 r->step,
201 1);
Guido van Rossum2586bf01993-11-01 16:21:44 +0000202}
Guido van Rossum12d12c51993-10-26 17:58:25 +0000203
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000204static PyObject *
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000205range_tolist(self, args)
206rangeobject *self;
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000207PyObject *args;
Guido van Rossum2586bf01993-11-01 16:21:44 +0000208{
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000209 PyObject *thelist;
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000210 int j;
211 int len = self->len * self->reps;
212
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000213 if (! PyArg_Parse(args, ""))
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000214 return NULL;
215
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000216 if ((thelist = PyList_New(len)) == NULL)
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000217 return NULL;
218
219 for (j = 0; j < len; ++j)
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000220 if ((PyList_SetItem(thelist, j, (PyObject *) PyInt_FromLong(
221 self->start + (j % self->len) * self->step))) < 0)
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000222 return NULL;
223
224 return thelist;
Guido van Rossum2586bf01993-11-01 16:21:44 +0000225}
226
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000227static PyObject *
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000228range_getattr(r, name)
Guido van Rossum2586bf01993-11-01 16:21:44 +0000229 rangeobject *r;
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000230 char *name;
Guido van Rossum2586bf01993-11-01 16:21:44 +0000231{
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000232 static PyMethodDef range_methods[] = {
233 {"tolist", (PyCFunction)range_tolist},
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000234 {NULL, NULL}
235 };
236
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000237 return Py_FindMethod(range_methods, (PyObject *) r, name);
Guido van Rossum12d12c51993-10-26 17:58:25 +0000238}
239
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000240static PySequenceMethods range_as_sequence = {
Guido van Rossum03093a21994-09-28 15:51:32 +0000241 (inquiry)range_length, /*sq_length*/
242 (binaryfunc)range_concat, /*sq_concat*/
243 (intargfunc)range_repeat, /*sq_repeat*/
244 (intargfunc)range_item, /*sq_item*/
245 (intintargfunc)range_slice, /*sq_slice*/
Guido van Rossum12d12c51993-10-26 17:58:25 +0000246 0, /*sq_ass_item*/
247 0, /*sq_ass_slice*/
248};
249
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000250PyTypeObject PyRange_Type = {
251 PyObject_HEAD_INIT(&PyType_Type)
Guido van Rossum12d12c51993-10-26 17:58:25 +0000252 0, /* Number of items for varobject */
Guido van Rossum2586bf01993-11-01 16:21:44 +0000253 "xrange", /* Name of this type */
Guido van Rossum12d12c51993-10-26 17:58:25 +0000254 sizeof(rangeobject), /* Basic object size */
255 0, /* Item size for varobject */
Guido van Rossum03093a21994-09-28 15:51:32 +0000256 (destructor)range_dealloc, /*tp_dealloc*/
257 (printfunc)range_print, /*tp_print*/
258 (getattrfunc)range_getattr, /*tp_getattr*/
Guido van Rossum12d12c51993-10-26 17:58:25 +0000259 0, /*tp_setattr*/
Guido van Rossum03093a21994-09-28 15:51:32 +0000260 (cmpfunc)range_compare, /*tp_compare*/
261 (reprfunc)range_repr, /*tp_repr*/
Guido van Rossum12d12c51993-10-26 17:58:25 +0000262 0, /*tp_as_number*/
263 &range_as_sequence, /*tp_as_sequence*/
264 0, /*tp_as_mapping*/
265};