blob: 3c3164ea4504755a2249578099558c4712c3b9be [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 *
Fred Drake45cfbcc2000-07-09 06:21:27 +000025PyRange_New(long start, long len, long step, int reps)
Guido van Rossum12d12c51993-10-26 17:58:25 +000026{
Guido van Rossumc0b618a1997-05-02 03:12:38 +000027 rangeobject *obj = PyObject_NEW(rangeobject, &PyRange_Type);
Guido van Rossum12d12c51993-10-26 17:58:25 +000028
29 obj->start = start;
30 obj->len = len;
31 obj->step = step;
Guido van Rossum7d6aa511993-12-21 22:50:31 +000032 obj->reps = reps;
Guido van Rossum12d12c51993-10-26 17:58:25 +000033
Guido van Rossumc0b618a1997-05-02 03:12:38 +000034 return (PyObject *) obj;
Guido van Rossum12d12c51993-10-26 17:58:25 +000035}
36
37static void
Fred Drake45cfbcc2000-07-09 06:21:27 +000038range_dealloc(rangeobject *r)
Guido van Rossum12d12c51993-10-26 17:58:25 +000039{
Guido van Rossumb18618d2000-05-03 23:44:39 +000040 PyObject_DEL(r);
Guido van Rossum12d12c51993-10-26 17:58:25 +000041}
42
Guido van Rossumc0b618a1997-05-02 03:12:38 +000043static PyObject *
Fred Drake45cfbcc2000-07-09 06:21:27 +000044range_item(rangeobject *r, int i)
Guido van Rossum12d12c51993-10-26 17:58:25 +000045{
Guido van Rossum7d6aa511993-12-21 22:50:31 +000046 if (i < 0 || i >= r->len * r->reps) {
Guido van Rossumc0b618a1997-05-02 03:12:38 +000047 PyErr_SetString(PyExc_IndexError,
Guido van Rossum5dadf7e1999-01-09 21:40:35 +000048 "xrange object index out of range");
Guido van Rossum12d12c51993-10-26 17:58:25 +000049 return NULL;
50 }
51
Guido van Rossumc0b618a1997-05-02 03:12:38 +000052 return PyInt_FromLong(r->start + (i % r->len) * r->step);
Guido van Rossum12d12c51993-10-26 17:58:25 +000053}
54
55static int
Fred Drake45cfbcc2000-07-09 06:21:27 +000056range_length(rangeobject *r)
Guido van Rossum12d12c51993-10-26 17:58:25 +000057{
Guido van Rossum7d6aa511993-12-21 22:50:31 +000058 return r->len * r->reps;
59}
60
61static int
Fred Drake45cfbcc2000-07-09 06:21:27 +000062range_print(rangeobject *r, FILE *fp, int flags)
Guido van Rossum7d6aa511993-12-21 22:50:31 +000063{
64 int i, j;
65
66 fprintf(fp, "(");
67 for (i = 0; i < r->reps; ++i)
68 for (j = 0; j < r->len; ++j) {
69 if (j > 0 || i > 0)
70 fprintf(fp, ", ");
71
Guido van Rossumda9c2711996-12-05 21:58:58 +000072 fprintf(fp, "%ld", r->start + j * r->step);
Guido van Rossum7d6aa511993-12-21 22:50:31 +000073 }
74
75 if (r->len == 1 && r->reps == 1)
76 fprintf(fp, ",");
77 fprintf(fp, ")");
78 return 0;
Guido van Rossum12d12c51993-10-26 17:58:25 +000079}
80
Guido van Rossumc0b618a1997-05-02 03:12:38 +000081static PyObject *
Fred Drake45cfbcc2000-07-09 06:21:27 +000082range_repr(rangeobject *r)
Guido van Rossum12d12c51993-10-26 17:58:25 +000083{
84 char buf[80];
Guido van Rossum03093a21994-09-28 15:51:32 +000085 sprintf(buf, "(xrange(%ld, %ld, %ld) * %d)",
Guido van Rossum7d6aa511993-12-21 22:50:31 +000086 r->start,
87 r->start + r->len * r->step,
88 r->step,
89 r->reps);
Guido van Rossumc0b618a1997-05-02 03:12:38 +000090 return PyString_FromString(buf);
Guido van Rossum12d12c51993-10-26 17:58:25 +000091}
92
Guido van Rossumc0b618a1997-05-02 03:12:38 +000093static PyObject *
Fred Drake45cfbcc2000-07-09 06:21:27 +000094range_concat(rangeobject *r, PyObject *obj)
Guido van Rossum7d6aa511993-12-21 22:50:31 +000095{
Guido van Rossum5dadf7e1999-01-09 21:40:35 +000096 PyErr_SetString(PyExc_TypeError, "cannot concatenate xrange objects");
Guido van Rossum7d6aa511993-12-21 22:50:31 +000097 return NULL;
98}
99
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000100static PyObject *
Fred Drake45cfbcc2000-07-09 06:21:27 +0000101range_repeat(rangeobject *r, int n)
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000102{
103 if (n < 0)
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000104 return (PyObject *) PyRange_New(0, 0, 1, 1);
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000105
106 else if (n == 1) {
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000107 Py_INCREF(r);
108 return (PyObject *) r;
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000109 }
110
111 else
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000112 return (PyObject *) PyRange_New(
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000113 r->start,
114 r->len,
115 r->step,
116 r->reps * n);
117}
118
Guido van Rossum12d12c51993-10-26 17:58:25 +0000119static int
Fred Drake45cfbcc2000-07-09 06:21:27 +0000120range_compare(rangeobject *r1, rangeobject *r2)
Guido van Rossum12d12c51993-10-26 17:58:25 +0000121{
122 if (r1->start != r2->start)
123 return r1->start - r2->start;
124
125 else if (r1->step != r2->step)
126 return r1->step - r2->step;
127
128 else if (r1->len != r2->len)
129 return r1->len - r2->len;
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000130
131 else
132 return r1->reps - r2->reps;
Guido van Rossum12d12c51993-10-26 17:58:25 +0000133}
134
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000135static PyObject *
Fred Drake45cfbcc2000-07-09 06:21:27 +0000136range_slice(rangeobject *r, int low, int high)
Guido van Rossum12d12c51993-10-26 17:58:25 +0000137{
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000138 if (r->reps != 1) {
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000139 PyErr_SetString(PyExc_TypeError,
Guido van Rossum5dadf7e1999-01-09 21:40:35 +0000140 "cannot slice a replicated xrange");
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000141 return NULL;
142 }
143 if (low < 0)
144 low = 0;
145 else if (low > r->len)
146 low = r->len;
147 if (high < 0)
148 high = 0;
149 if (high < low)
150 high = low;
151 else if (high > r->len)
152 high = r->len;
153
154 if (low == 0 && high == r->len) {
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000155 Py_INCREF(r);
156 return (PyObject *) r;
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000157 }
158
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000159 return (PyObject *) PyRange_New(
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000160 low * r->step + r->start,
161 high - low,
162 r->step,
163 1);
Guido van Rossum2586bf01993-11-01 16:21:44 +0000164}
Guido van Rossum12d12c51993-10-26 17:58:25 +0000165
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000166static PyObject *
Fred Drake45cfbcc2000-07-09 06:21:27 +0000167range_tolist(rangeobject *self, PyObject *args)
Guido van Rossum2586bf01993-11-01 16:21:44 +0000168{
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000169 PyObject *thelist;
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000170 int j;
171 int len = self->len * self->reps;
172
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000173 if (! PyArg_Parse(args, ""))
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000174 return NULL;
175
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000176 if ((thelist = PyList_New(len)) == NULL)
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000177 return NULL;
178
179 for (j = 0; j < len; ++j)
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000180 if ((PyList_SetItem(thelist, j, (PyObject *) PyInt_FromLong(
181 self->start + (j % self->len) * self->step))) < 0)
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000182 return NULL;
183
184 return thelist;
Guido van Rossum2586bf01993-11-01 16:21:44 +0000185}
186
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000187static PyObject *
Fred Drake45cfbcc2000-07-09 06:21:27 +0000188range_getattr(rangeobject *r, char *name)
Guido van Rossum2586bf01993-11-01 16:21:44 +0000189{
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000190 static PyMethodDef range_methods[] = {
191 {"tolist", (PyCFunction)range_tolist},
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000192 {NULL, NULL}
193 };
194
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000195 return Py_FindMethod(range_methods, (PyObject *) r, name);
Guido van Rossum12d12c51993-10-26 17:58:25 +0000196}
197
Fred Drake56780252000-06-15 14:50:20 +0000198static int
Fred Drake45cfbcc2000-07-09 06:21:27 +0000199range_contains(rangeobject *r, PyObject *obj)
Fred Drake56780252000-06-15 14:50:20 +0000200{
201 long num = PyInt_AsLong(obj);
202
203 if (num < 0 && PyErr_Occurred())
204 return -1;
205
206 if (num < r->start || (num - r->start) % r->step)
207 return 0;
208 if (num > (r->start + (r->len * r->step)))
209 return 0;
210 return 1;
211}
212
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000213static PySequenceMethods range_as_sequence = {
Guido van Rossum03093a21994-09-28 15:51:32 +0000214 (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*/
Guido van Rossum12d12c51993-10-26 17:58:25 +0000219 0, /*sq_ass_item*/
220 0, /*sq_ass_slice*/
Fred Drake56780252000-06-15 14:50:20 +0000221 (objobjproc)range_contains, /*sq_contains*/
Guido van Rossum12d12c51993-10-26 17:58:25 +0000222};
223
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000224PyTypeObject PyRange_Type = {
225 PyObject_HEAD_INIT(&PyType_Type)
Guido van Rossum12d12c51993-10-26 17:58:25 +0000226 0, /* Number of items for varobject */
Guido van Rossum2586bf01993-11-01 16:21:44 +0000227 "xrange", /* Name of this type */
Guido van Rossum12d12c51993-10-26 17:58:25 +0000228 sizeof(rangeobject), /* Basic object size */
229 0, /* Item size for varobject */
Guido van Rossum03093a21994-09-28 15:51:32 +0000230 (destructor)range_dealloc, /*tp_dealloc*/
231 (printfunc)range_print, /*tp_print*/
232 (getattrfunc)range_getattr, /*tp_getattr*/
Guido van Rossum12d12c51993-10-26 17:58:25 +0000233 0, /*tp_setattr*/
Guido van Rossum03093a21994-09-28 15:51:32 +0000234 (cmpfunc)range_compare, /*tp_compare*/
235 (reprfunc)range_repr, /*tp_repr*/
Guido van Rossum12d12c51993-10-26 17:58:25 +0000236 0, /*tp_as_number*/
237 &range_as_sequence, /*tp_as_sequence*/
238 0, /*tp_as_mapping*/
Fred Drake56780252000-06-15 14:50:20 +0000239 0, /*tp_hash*/
240 0, /*tp_call*/
241 0, /*tp_str*/
242 0, /*tp_getattro*/
243 0, /*tp_setattro*/
244 0, /*tp_as_buffer*/
245 Py_TPFLAGS_DEFAULT, /*tp_flags*/
Guido van Rossum12d12c51993-10-26 17:58:25 +0000246};