blob: 002f94a40ca87e71d3ec28a9e690053ac58f5b9b [file] [log] [blame]
Guido van Rossum12d12c51993-10-26 17:58:25 +00001
2/* Range object implementation */
3
Guido van Rossumc0b618a1997-05-02 03:12:38 +00004#include "Python.h"
Thomas Woutersefafcea2001-07-09 12:30:54 +00005
Guido van Rossum12d12c51993-10-26 17:58:25 +00006typedef struct {
Guido van Rossumc0b618a1997-05-02 03:12:38 +00007 PyObject_HEAD
Guido van Rossum12d12c51993-10-26 17:58:25 +00008 long start;
9 long step;
10 long len;
Guido van Rossum12d12c51993-10-26 17:58:25 +000011} rangeobject;
12
Thomas Woutersefafcea2001-07-09 12:30:54 +000013PyObject *
14PyRange_New(long start, long len, long step, int reps)
15{
Fred Draked9018322002-05-02 19:56:55 +000016 rangeobject *obj;
Guido van Rossum12d12c51993-10-26 17:58:25 +000017
Fred Draked9018322002-05-02 19:56:55 +000018 if (reps != 1) {
19 PyErr_SetString(PyExc_ValueError,
20 "PyRange_New's 'repetitions' argument must be 1");
21 return NULL;
22 }
23
24 obj = PyObject_New(rangeobject, &PyRange_Type);
Guido van Rossum9e8f4ea2000-12-14 14:59:53 +000025 if (obj == NULL)
26 return NULL;
27
Fred Draked9018322002-05-02 19:56:55 +000028 if (len == 0) {
Guido van Rossum65e0b992001-01-15 18:58:56 +000029 start = 0;
30 len = 0;
31 step = 1;
Guido van Rossum65e0b992001-01-15 18:58:56 +000032 }
33 else {
34 long last = start + (len - 1) * step;
35 if ((step > 0) ?
Thomas Woutersefafcea2001-07-09 12:30:54 +000036 (last > (PyInt_GetMax() - step)) :
37 (last < (-1 - PyInt_GetMax() - step))) {
Guido van Rossum65e0b992001-01-15 18:58:56 +000038 PyErr_SetString(PyExc_OverflowError,
39 "integer addition");
40 return NULL;
Thomas Woutersefafcea2001-07-09 12:30:54 +000041 }
Guido van Rossum65e0b992001-01-15 18:58:56 +000042 }
Guido van Rossum12d12c51993-10-26 17:58:25 +000043 obj->start = start;
44 obj->len = len;
45 obj->step = step;
Guido van Rossum12d12c51993-10-26 17:58:25 +000046
Guido van Rossumc0b618a1997-05-02 03:12:38 +000047 return (PyObject *) obj;
Guido van Rossum12d12c51993-10-26 17:58:25 +000048}
49
Guido van Rossumc0b618a1997-05-02 03:12:38 +000050static PyObject *
Fred Drake45cfbcc2000-07-09 06:21:27 +000051range_item(rangeobject *r, int i)
Guido van Rossum12d12c51993-10-26 17:58:25 +000052{
Fred Draked9018322002-05-02 19:56:55 +000053 if (i < 0 || i >= r->len) {
54 PyErr_SetString(PyExc_IndexError,
Guido van Rossum5dadf7e1999-01-09 21:40:35 +000055 "xrange object index out of range");
Fred Draked9018322002-05-02 19:56:55 +000056 return NULL;
57 }
Guido van Rossumc0b618a1997-05-02 03:12:38 +000058 return PyInt_FromLong(r->start + (i % r->len) * r->step);
Guido van Rossum12d12c51993-10-26 17:58:25 +000059}
60
61static int
Fred Drake45cfbcc2000-07-09 06:21:27 +000062range_length(rangeobject *r)
Guido van Rossum12d12c51993-10-26 17:58:25 +000063{
Fred Draked9018322002-05-02 19:56:55 +000064 return r->len;
Guido van Rossum7d6aa511993-12-21 22:50:31 +000065}
66
Guido van Rossumc0b618a1997-05-02 03:12:38 +000067static PyObject *
Fred Drake45cfbcc2000-07-09 06:21:27 +000068range_repr(rangeobject *r)
Guido van Rossum12d12c51993-10-26 17:58:25 +000069{
Barry Warsaw7ce36942001-08-24 18:34:26 +000070 PyObject *rtn;
71
Tim Peters72d421b2000-08-04 03:05:40 +000072 if (r->start == 0 && r->step == 1)
Barry Warsaw7ce36942001-08-24 18:34:26 +000073 rtn = PyString_FromFormat("xrange(%ld)",
74 r->start + r->len * r->step);
Tim Peters72d421b2000-08-04 03:05:40 +000075
76 else if (r->step == 1)
Barry Warsaw7ce36942001-08-24 18:34:26 +000077 rtn = PyString_FromFormat("xrange(%ld, %ld)",
78 r->start,
79 r->start + r->len * r->step);
Tim Peters72d421b2000-08-04 03:05:40 +000080
81 else
Barry Warsaw7ce36942001-08-24 18:34:26 +000082 rtn = PyString_FromFormat("xrange(%ld, %ld, %ld)",
83 r->start,
84 r->start + r->len * r->step,
85 r->step);
Barry Warsaw7ce36942001-08-24 18:34:26 +000086 return rtn;
Thomas Woutersefafcea2001-07-09 12:30:54 +000087}
88
Guido van Rossumc0b618a1997-05-02 03:12:38 +000089static PySequenceMethods range_as_sequence = {
Fred Draked9018322002-05-02 19:56:55 +000090 (inquiry)range_length, /* sq_length */
91 0, /* sq_concat */
92 0, /* sq_repeat */
93 (intargfunc)range_item, /* sq_item */
94 0, /* sq_slice */
Guido van Rossum12d12c51993-10-26 17:58:25 +000095};
96
Raymond Hettinger48165d42002-06-05 20:08:48 +000097staticforward PyObject * range_iter(PyObject *seq);
98
Guido van Rossumc0b618a1997-05-02 03:12:38 +000099PyTypeObject PyRange_Type = {
100 PyObject_HEAD_INIT(&PyType_Type)
Fred Draked9018322002-05-02 19:56:55 +0000101 0, /* Number of items for varobject */
102 "xrange", /* Name of this type */
103 sizeof(rangeobject), /* Basic object size */
104 0, /* Item size for varobject */
105 (destructor)PyObject_Del, /* tp_dealloc */
106 0, /* tp_print */
107 0, /* tp_getattr */
108 0, /* tp_setattr */
109 0, /* tp_compare */
110 (reprfunc)range_repr, /* tp_repr */
111 0, /* tp_as_number */
112 &range_as_sequence, /* tp_as_sequence */
113 0, /* tp_as_mapping */
114 0, /* tp_hash */
115 0, /* tp_call */
116 0, /* tp_str */
Raymond Hettinger48165d42002-06-05 20:08:48 +0000117 0, /* tp_getattro */
Fred Draked9018322002-05-02 19:56:55 +0000118 0, /* tp_setattro */
119 0, /* tp_as_buffer */
120 Py_TPFLAGS_DEFAULT, /* tp_flags */
121 0, /* tp_doc */
Martin v. Löwise4526592002-05-08 08:49:27 +0000122 0, /* tp_traverse */
123 0, /* tp_clear */
124 0, /* tp_richcompare */
125 0, /* tp_weaklistoffset */
Raymond Hettinger48165d42002-06-05 20:08:48 +0000126 (getiterfunc)range_iter, /* tp_iter */
Guido van Rossum12d12c51993-10-26 17:58:25 +0000127};
Raymond Hettinger48165d42002-06-05 20:08:48 +0000128
129/*********************** Xrange Iterator **************************/
130
131typedef struct {
132 PyObject_HEAD
133 long index;
134 long start;
135 long step;
136 long len;
137} rangeiterobject;
138
139PyTypeObject Pyrangeiter_Type;
140
141PyObject *
142range_iter(PyObject *seq)
143{
144 rangeiterobject *it;
145
146 if (!PyRange_Check(seq)) {
147 PyErr_BadInternalCall();
148 return NULL;
149 }
150 it = PyObject_New(rangeiterobject, &Pyrangeiter_Type);
151 if (it == NULL)
152 return NULL;
153 it->index = 0;
154 it->start = ((rangeobject *)seq)->start;
155 it->step = ((rangeobject *)seq)->step;
156 it->len = ((rangeobject *)seq)->len;
157 return (PyObject *)it;
158}
159
160static PyObject *
161rangeiter_getiter(PyObject *it)
162{
163 Py_INCREF(it);
164 return it;
165}
166
167static PyObject *
168rangeiter_next(rangeiterobject *r)
169{
170 if (r->index < r->len)
171 return PyInt_FromLong(r->start + (r->index++) * r->step);
172 PyErr_SetObject(PyExc_StopIteration, Py_None);
173 return NULL;
174}
175
176static PyMethodDef rangeiter_methods[] = {
177 {"next", (PyCFunction)rangeiter_next, METH_NOARGS,
178 "it.next() -- get the next value, or raise StopIteration"},
179 {NULL, NULL} /* sentinel */
180};
181
182PyTypeObject Pyrangeiter_Type = {
183 PyObject_HEAD_INIT(&PyType_Type)
184 0, /* ob_size */
185 "rangeiterator", /* tp_name */
186 sizeof(rangeiterobject), /* tp_basicsize */
187 0, /* tp_itemsize */
188 /* methods */
189 (destructor)PyObject_Del, /* tp_dealloc */
190 0, /* tp_print */
191 0, /* tp_getattr */
192 0, /* tp_setattr */
193 0, /* tp_compare */
194 0, /* tp_repr */
195 0, /* tp_as_number */
196 0, /* tp_as_sequence */
197 0, /* tp_as_mapping */
198 0, /* tp_hash */
199 0, /* tp_call */
200 0, /* tp_str */
201 PyObject_GenericGetAttr, /* tp_getattro */
202 0, /* tp_setattro */
203 0, /* tp_as_buffer */
204 Py_TPFLAGS_DEFAULT, /* tp_flags */
205 0, /* tp_doc */
206 0, /* tp_traverse */
207 0, /* tp_clear */
208 0, /* tp_richcompare */
209 0, /* tp_weaklistoffset */
210 (getiterfunc)rangeiter_getiter, /* tp_iter */
211 (iternextfunc)rangeiter_next, /* tp_iternext */
212 rangeiter_methods, /* tp_methods */
213};
214