blob: 7eb2dc38f5acc973317998cf5ef68228ebe233cf [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 Rossumfd71b9e2000-06-30 23:50:40 +00007Copyright (c) 2000, BeOpen.com.
8Copyright (c) 1995-2000, Corporation for National Research Initiatives.
9Copyright (c) 1990-1995, Stichting Mathematisch Centrum.
10All rights reserved.
Guido van Rossum12d12c51993-10-26 17:58:25 +000011
Guido van Rossumfd71b9e2000-06-30 23:50:40 +000012See the file "Misc/COPYRIGHT" for information on usage and
13redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
Guido van Rossum12d12c51993-10-26 17:58:25 +000014
15******************************************************************/
16
17/* Range object implementation */
18
Guido van Rossumc0b618a1997-05-02 03:12:38 +000019#include "Python.h"
Guido van Rossum12d12c51993-10-26 17:58:25 +000020
21typedef struct {
Guido van Rossumc0b618a1997-05-02 03:12:38 +000022 PyObject_HEAD
Guido van Rossum12d12c51993-10-26 17:58:25 +000023 long start;
24 long step;
25 long len;
Guido van Rossum7d6aa511993-12-21 22:50:31 +000026 int reps;
Guido van Rossum12d12c51993-10-26 17:58:25 +000027} rangeobject;
28
29
Guido van Rossumc0b618a1997-05-02 03:12:38 +000030PyObject *
31PyRange_New(start, len, step, reps)
Guido van Rossum12d12c51993-10-26 17:58:25 +000032 long start, len, step;
Guido van Rossum7d6aa511993-12-21 22:50:31 +000033 int reps;
Guido van Rossum12d12c51993-10-26 17:58:25 +000034{
Guido van Rossumc0b618a1997-05-02 03:12:38 +000035 rangeobject *obj = PyObject_NEW(rangeobject, &PyRange_Type);
Guido van Rossum12d12c51993-10-26 17:58:25 +000036
37 obj->start = start;
38 obj->len = len;
39 obj->step = step;
Guido van Rossum7d6aa511993-12-21 22:50:31 +000040 obj->reps = reps;
Guido van Rossum12d12c51993-10-26 17:58:25 +000041
Guido van Rossumc0b618a1997-05-02 03:12:38 +000042 return (PyObject *) obj;
Guido van Rossum12d12c51993-10-26 17:58:25 +000043}
44
45static void
46range_dealloc(r)
47 rangeobject *r;
48{
Guido van Rossumb18618d2000-05-03 23:44:39 +000049 PyObject_DEL(r);
Guido van Rossum12d12c51993-10-26 17:58:25 +000050}
51
Guido van Rossumc0b618a1997-05-02 03:12:38 +000052static PyObject *
Guido van Rossum12d12c51993-10-26 17:58:25 +000053range_item(r, i)
54 rangeobject *r;
55 int i;
56{
Guido van Rossum7d6aa511993-12-21 22:50:31 +000057 if (i < 0 || i >= r->len * r->reps) {
Guido van Rossumc0b618a1997-05-02 03:12:38 +000058 PyErr_SetString(PyExc_IndexError,
Guido van Rossum5dadf7e1999-01-09 21:40:35 +000059 "xrange object index out of range");
Guido van Rossum12d12c51993-10-26 17:58:25 +000060 return NULL;
61 }
62
Guido van Rossumc0b618a1997-05-02 03:12:38 +000063 return PyInt_FromLong(r->start + (i % r->len) * r->step);
Guido van Rossum12d12c51993-10-26 17:58:25 +000064}
65
66static int
67range_length(r)
68 rangeobject *r;
69{
Guido van Rossum7d6aa511993-12-21 22:50:31 +000070 return r->len * r->reps;
71}
72
73static int
74range_print(r, fp, flags)
75 rangeobject *r;
76 FILE *fp;
77 int flags;
78{
79 int i, j;
80
81 fprintf(fp, "(");
82 for (i = 0; i < r->reps; ++i)
83 for (j = 0; j < r->len; ++j) {
84 if (j > 0 || i > 0)
85 fprintf(fp, ", ");
86
Guido van Rossumda9c2711996-12-05 21:58:58 +000087 fprintf(fp, "%ld", r->start + j * r->step);
Guido van Rossum7d6aa511993-12-21 22:50:31 +000088 }
89
90 if (r->len == 1 && r->reps == 1)
91 fprintf(fp, ",");
92 fprintf(fp, ")");
93 return 0;
Guido van Rossum12d12c51993-10-26 17:58:25 +000094}
95
Guido van Rossumc0b618a1997-05-02 03:12:38 +000096static PyObject *
Guido van Rossum12d12c51993-10-26 17:58:25 +000097range_repr(r)
98 rangeobject *r;
99{
100 char buf[80];
Guido van Rossum03093a21994-09-28 15:51:32 +0000101 sprintf(buf, "(xrange(%ld, %ld, %ld) * %d)",
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000102 r->start,
103 r->start + r->len * r->step,
104 r->step,
105 r->reps);
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000106 return PyString_FromString(buf);
Guido van Rossum12d12c51993-10-26 17:58:25 +0000107}
108
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000109static PyObject *
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000110range_concat(r, obj)
111 rangeobject *r;
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000112 PyObject *obj;
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000113{
Guido van Rossum5dadf7e1999-01-09 21:40:35 +0000114 PyErr_SetString(PyExc_TypeError, "cannot concatenate xrange objects");
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000115 return NULL;
116}
117
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000118static PyObject *
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000119range_repeat(r, n)
120 rangeobject *r;
121 int n;
122{
123 if (n < 0)
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000124 return (PyObject *) PyRange_New(0, 0, 1, 1);
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000125
126 else if (n == 1) {
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000127 Py_INCREF(r);
128 return (PyObject *) r;
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000129 }
130
131 else
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000132 return (PyObject *) PyRange_New(
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000133 r->start,
134 r->len,
135 r->step,
136 r->reps * n);
137}
138
Guido van Rossum12d12c51993-10-26 17:58:25 +0000139static int
140range_compare(r1, r2)
141 rangeobject *r1, *r2;
142{
143 if (r1->start != r2->start)
144 return r1->start - r2->start;
145
146 else if (r1->step != r2->step)
147 return r1->step - r2->step;
148
149 else if (r1->len != r2->len)
150 return r1->len - r2->len;
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000151
152 else
153 return r1->reps - r2->reps;
Guido van Rossum12d12c51993-10-26 17:58:25 +0000154}
155
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000156static PyObject *
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000157range_slice(r, low, high)
Guido van Rossum12d12c51993-10-26 17:58:25 +0000158 rangeobject *r;
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000159 int low, high;
Guido van Rossum12d12c51993-10-26 17:58:25 +0000160{
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000161 if (r->reps != 1) {
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000162 PyErr_SetString(PyExc_TypeError,
Guido van Rossum5dadf7e1999-01-09 21:40:35 +0000163 "cannot slice a replicated xrange");
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000164 return NULL;
165 }
166 if (low < 0)
167 low = 0;
168 else if (low > r->len)
169 low = r->len;
170 if (high < 0)
171 high = 0;
172 if (high < low)
173 high = low;
174 else if (high > r->len)
175 high = r->len;
176
177 if (low == 0 && high == r->len) {
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000178 Py_INCREF(r);
179 return (PyObject *) r;
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000180 }
181
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000182 return (PyObject *) PyRange_New(
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000183 low * r->step + r->start,
184 high - low,
185 r->step,
186 1);
Guido van Rossum2586bf01993-11-01 16:21:44 +0000187}
Guido van Rossum12d12c51993-10-26 17:58:25 +0000188
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000189static PyObject *
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000190range_tolist(self, args)
191rangeobject *self;
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000192PyObject *args;
Guido van Rossum2586bf01993-11-01 16:21:44 +0000193{
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000194 PyObject *thelist;
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000195 int j;
196 int len = self->len * self->reps;
197
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000198 if (! PyArg_Parse(args, ""))
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000199 return NULL;
200
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000201 if ((thelist = PyList_New(len)) == NULL)
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000202 return NULL;
203
204 for (j = 0; j < len; ++j)
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000205 if ((PyList_SetItem(thelist, j, (PyObject *) PyInt_FromLong(
206 self->start + (j % self->len) * self->step))) < 0)
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000207 return NULL;
208
209 return thelist;
Guido van Rossum2586bf01993-11-01 16:21:44 +0000210}
211
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000212static PyObject *
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000213range_getattr(r, name)
Guido van Rossum2586bf01993-11-01 16:21:44 +0000214 rangeobject *r;
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000215 char *name;
Guido van Rossum2586bf01993-11-01 16:21:44 +0000216{
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000217 static PyMethodDef range_methods[] = {
218 {"tolist", (PyCFunction)range_tolist},
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000219 {NULL, NULL}
220 };
221
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000222 return Py_FindMethod(range_methods, (PyObject *) r, name);
Guido van Rossum12d12c51993-10-26 17:58:25 +0000223}
224
Fred Drake56780252000-06-15 14:50:20 +0000225static int
226range_contains(r, obj)
227 rangeobject * r;
228 PyObject * obj;
229{
230 long num = PyInt_AsLong(obj);
231
232 if (num < 0 && PyErr_Occurred())
233 return -1;
234
235 if (num < r->start || (num - r->start) % r->step)
236 return 0;
237 if (num > (r->start + (r->len * r->step)))
238 return 0;
239 return 1;
240}
241
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000242static PySequenceMethods range_as_sequence = {
Guido van Rossum03093a21994-09-28 15:51:32 +0000243 (inquiry)range_length, /*sq_length*/
244 (binaryfunc)range_concat, /*sq_concat*/
245 (intargfunc)range_repeat, /*sq_repeat*/
246 (intargfunc)range_item, /*sq_item*/
247 (intintargfunc)range_slice, /*sq_slice*/
Guido van Rossum12d12c51993-10-26 17:58:25 +0000248 0, /*sq_ass_item*/
249 0, /*sq_ass_slice*/
Fred Drake56780252000-06-15 14:50:20 +0000250 (objobjproc)range_contains, /*sq_contains*/
Guido van Rossum12d12c51993-10-26 17:58:25 +0000251};
252
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000253PyTypeObject PyRange_Type = {
254 PyObject_HEAD_INIT(&PyType_Type)
Guido van Rossum12d12c51993-10-26 17:58:25 +0000255 0, /* Number of items for varobject */
Guido van Rossum2586bf01993-11-01 16:21:44 +0000256 "xrange", /* Name of this type */
Guido van Rossum12d12c51993-10-26 17:58:25 +0000257 sizeof(rangeobject), /* Basic object size */
258 0, /* Item size for varobject */
Guido van Rossum03093a21994-09-28 15:51:32 +0000259 (destructor)range_dealloc, /*tp_dealloc*/
260 (printfunc)range_print, /*tp_print*/
261 (getattrfunc)range_getattr, /*tp_getattr*/
Guido van Rossum12d12c51993-10-26 17:58:25 +0000262 0, /*tp_setattr*/
Guido van Rossum03093a21994-09-28 15:51:32 +0000263 (cmpfunc)range_compare, /*tp_compare*/
264 (reprfunc)range_repr, /*tp_repr*/
Guido van Rossum12d12c51993-10-26 17:58:25 +0000265 0, /*tp_as_number*/
266 &range_as_sequence, /*tp_as_sequence*/
267 0, /*tp_as_mapping*/
Fred Drake56780252000-06-15 14:50:20 +0000268 0, /*tp_hash*/
269 0, /*tp_call*/
270 0, /*tp_str*/
271 0, /*tp_getattro*/
272 0, /*tp_setattro*/
273 0, /*tp_as_buffer*/
274 Py_TPFLAGS_DEFAULT, /*tp_flags*/
Guido van Rossum12d12c51993-10-26 17:58:25 +0000275};