blob: 20b077f4f9e69e8636ae54b06bbe312abed935b7 [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
Guido van Rossumc0b618a1997-05-02 03:12:38 +000061static PyObject *
Fred Drake45cfbcc2000-07-09 06:21:27 +000062range_repr(rangeobject *r)
Guido van Rossum12d12c51993-10-26 17:58:25 +000063{
Tim Peters72d421b2000-08-04 03:05:40 +000064 /* buffers must be big enough to hold 3 longs + an int +
65 * a bit of "(xrange(...) * ...)" text.
66 */
67 char buf1[250];
68 char buf2[250];
Fred Drake2b83b462000-08-03 17:43:02 +000069
Tim Peters72d421b2000-08-04 03:05:40 +000070 if (r->start == 0 && r->step == 1)
Fred Drakec76e0e52000-08-04 02:34:41 +000071 sprintf(buf1, "xrange(%ld)", r->start + r->len * r->step);
Tim Peters72d421b2000-08-04 03:05:40 +000072
73 else if (r->step == 1)
74 sprintf(buf1, "xrange(%ld, %ld)",
75 r->start,
76 r->start + r->len * r->step);
77
78 else
79 sprintf(buf1, "xrange(%ld, %ld, %ld)",
Fred Drakec76e0e52000-08-04 02:34:41 +000080 r->start,
81 r->start + r->len * r->step,
82 r->step);
Tim Peters72d421b2000-08-04 03:05:40 +000083
84 if (r->reps != 1)
Fred Drakec76e0e52000-08-04 02:34:41 +000085 sprintf(buf2, "(%s * %d)", buf1, r->reps);
Tim Peters72d421b2000-08-04 03:05:40 +000086
Fred Drake2b83b462000-08-03 17:43:02 +000087 return PyString_FromString(r->reps == 1 ? buf1 : buf2);
Guido van Rossum12d12c51993-10-26 17:58:25 +000088}
89
Guido van Rossumc0b618a1997-05-02 03:12:38 +000090static PyObject *
Fred Drake45cfbcc2000-07-09 06:21:27 +000091range_concat(rangeobject *r, PyObject *obj)
Guido van Rossum7d6aa511993-12-21 22:50:31 +000092{
Guido van Rossum5dadf7e1999-01-09 21:40:35 +000093 PyErr_SetString(PyExc_TypeError, "cannot concatenate xrange objects");
Guido van Rossum7d6aa511993-12-21 22:50:31 +000094 return NULL;
95}
96
Guido van Rossumc0b618a1997-05-02 03:12:38 +000097static PyObject *
Fred Drake45cfbcc2000-07-09 06:21:27 +000098range_repeat(rangeobject *r, int n)
Guido van Rossum7d6aa511993-12-21 22:50:31 +000099{
100 if (n < 0)
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000101 return (PyObject *) PyRange_New(0, 0, 1, 1);
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000102
103 else if (n == 1) {
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000104 Py_INCREF(r);
105 return (PyObject *) r;
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000106 }
107
108 else
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000109 return (PyObject *) PyRange_New(
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000110 r->start,
111 r->len,
112 r->step,
113 r->reps * n);
114}
115
Guido van Rossum12d12c51993-10-26 17:58:25 +0000116static int
Fred Drake45cfbcc2000-07-09 06:21:27 +0000117range_compare(rangeobject *r1, rangeobject *r2)
Guido van Rossum12d12c51993-10-26 17:58:25 +0000118{
119 if (r1->start != r2->start)
120 return r1->start - r2->start;
121
122 else if (r1->step != r2->step)
123 return r1->step - r2->step;
124
125 else if (r1->len != r2->len)
126 return r1->len - r2->len;
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000127
128 else
129 return r1->reps - r2->reps;
Guido van Rossum12d12c51993-10-26 17:58:25 +0000130}
131
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000132static PyObject *
Fred Drake45cfbcc2000-07-09 06:21:27 +0000133range_slice(rangeobject *r, int low, int high)
Guido van Rossum12d12c51993-10-26 17:58:25 +0000134{
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000135 if (r->reps != 1) {
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000136 PyErr_SetString(PyExc_TypeError,
Guido van Rossum5dadf7e1999-01-09 21:40:35 +0000137 "cannot slice a replicated xrange");
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000138 return NULL;
139 }
140 if (low < 0)
141 low = 0;
142 else if (low > r->len)
143 low = r->len;
144 if (high < 0)
145 high = 0;
146 if (high < low)
147 high = low;
148 else if (high > r->len)
149 high = r->len;
150
151 if (low == 0 && high == r->len) {
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000152 Py_INCREF(r);
153 return (PyObject *) r;
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000154 }
155
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000156 return (PyObject *) PyRange_New(
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000157 low * r->step + r->start,
158 high - low,
159 r->step,
160 1);
Guido van Rossum2586bf01993-11-01 16:21:44 +0000161}
Guido van Rossum12d12c51993-10-26 17:58:25 +0000162
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000163static PyObject *
Fred Drake45cfbcc2000-07-09 06:21:27 +0000164range_tolist(rangeobject *self, PyObject *args)
Guido van Rossum2586bf01993-11-01 16:21:44 +0000165{
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000166 PyObject *thelist;
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000167 int j;
168 int len = self->len * self->reps;
169
Fred Drake2b83b462000-08-03 17:43:02 +0000170 if (! PyArg_ParseTuple(args, ":tolist"))
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000171 return NULL;
172
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000173 if ((thelist = PyList_New(len)) == NULL)
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000174 return NULL;
175
176 for (j = 0; j < len; ++j)
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000177 if ((PyList_SetItem(thelist, j, (PyObject *) PyInt_FromLong(
178 self->start + (j % self->len) * self->step))) < 0)
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000179 return NULL;
180
181 return thelist;
Guido van Rossum2586bf01993-11-01 16:21:44 +0000182}
183
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000184static PyObject *
Fred Drake45cfbcc2000-07-09 06:21:27 +0000185range_getattr(rangeobject *r, char *name)
Guido van Rossum2586bf01993-11-01 16:21:44 +0000186{
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000187 static PyMethodDef range_methods[] = {
Fred Drake2b83b462000-08-03 17:43:02 +0000188 {"tolist", (PyCFunction)range_tolist, METH_VARARGS,
189 "tolist() -> list\n"
190 "Return a list object with the same values."},
Guido van Rossum7d6aa511993-12-21 22:50:31 +0000191 {NULL, NULL}
192 };
193
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000194 return Py_FindMethod(range_methods, (PyObject *) r, name);
Guido van Rossum12d12c51993-10-26 17:58:25 +0000195}
196
Fred Drake56780252000-06-15 14:50:20 +0000197static int
Fred Drake45cfbcc2000-07-09 06:21:27 +0000198range_contains(rangeobject *r, PyObject *obj)
Fred Drake56780252000-06-15 14:50:20 +0000199{
200 long num = PyInt_AsLong(obj);
Tim Peters72d421b2000-08-04 03:05:40 +0000201
Fred Drake56780252000-06-15 14:50:20 +0000202 if (num < 0 && PyErr_Occurred())
203 return -1;
Tim Peters72d421b2000-08-04 03:05:40 +0000204
Fred Drake56780252000-06-15 14:50:20 +0000205 if (num < r->start || (num - r->start) % r->step)
206 return 0;
207 if (num > (r->start + (r->len * r->step)))
208 return 0;
209 return 1;
210}
211
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000212static PySequenceMethods range_as_sequence = {
Guido van Rossum03093a21994-09-28 15:51:32 +0000213 (inquiry)range_length, /*sq_length*/
214 (binaryfunc)range_concat, /*sq_concat*/
215 (intargfunc)range_repeat, /*sq_repeat*/
216 (intargfunc)range_item, /*sq_item*/
217 (intintargfunc)range_slice, /*sq_slice*/
Guido van Rossum12d12c51993-10-26 17:58:25 +0000218 0, /*sq_ass_item*/
219 0, /*sq_ass_slice*/
Fred Drake56780252000-06-15 14:50:20 +0000220 (objobjproc)range_contains, /*sq_contains*/
Guido van Rossum12d12c51993-10-26 17:58:25 +0000221};
222
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000223PyTypeObject PyRange_Type = {
224 PyObject_HEAD_INIT(&PyType_Type)
Guido van Rossum12d12c51993-10-26 17:58:25 +0000225 0, /* Number of items for varobject */
Guido van Rossum2586bf01993-11-01 16:21:44 +0000226 "xrange", /* Name of this type */
Guido van Rossum12d12c51993-10-26 17:58:25 +0000227 sizeof(rangeobject), /* Basic object size */
228 0, /* Item size for varobject */
Guido van Rossum03093a21994-09-28 15:51:32 +0000229 (destructor)range_dealloc, /*tp_dealloc*/
Fred Drake2b83b462000-08-03 17:43:02 +0000230 0, /*tp_print*/
Guido van Rossum03093a21994-09-28 15:51:32 +0000231 (getattrfunc)range_getattr, /*tp_getattr*/
Guido van Rossum12d12c51993-10-26 17:58:25 +0000232 0, /*tp_setattr*/
Guido van Rossum03093a21994-09-28 15:51:32 +0000233 (cmpfunc)range_compare, /*tp_compare*/
Fred Drake2b83b462000-08-03 17:43:02 +0000234 (reprfunc)range_repr, /*tp_repr*/
Guido van Rossum12d12c51993-10-26 17:58:25 +0000235 0, /*tp_as_number*/
236 &range_as_sequence, /*tp_as_sequence*/
237 0, /*tp_as_mapping*/
Fred Drake56780252000-06-15 14:50:20 +0000238 0, /*tp_hash*/
239 0, /*tp_call*/
240 0, /*tp_str*/
241 0, /*tp_getattro*/
242 0, /*tp_setattro*/
243 0, /*tp_as_buffer*/
244 Py_TPFLAGS_DEFAULT, /*tp_flags*/
Guido van Rossum12d12c51993-10-26 17:58:25 +0000245};