blob: 8e8f77e610df4437df667acecb81f57643c971cc [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;
Martin v. Löwise4526592002-05-08 08:49:27 +000011 long index;
12 int used; /* Set to 1 if called by range_getiter */
Guido van Rossum12d12c51993-10-26 17:58:25 +000013} rangeobject;
14
Thomas Woutersefafcea2001-07-09 12:30:54 +000015PyObject *
16PyRange_New(long start, long len, long step, int reps)
17{
Fred Draked9018322002-05-02 19:56:55 +000018 rangeobject *obj;
Guido van Rossum12d12c51993-10-26 17:58:25 +000019
Fred Draked9018322002-05-02 19:56:55 +000020 if (reps != 1) {
21 PyErr_SetString(PyExc_ValueError,
22 "PyRange_New's 'repetitions' argument must be 1");
23 return NULL;
24 }
25
26 obj = PyObject_New(rangeobject, &PyRange_Type);
Guido van Rossum9e8f4ea2000-12-14 14:59:53 +000027 if (obj == NULL)
28 return NULL;
29
Fred Draked9018322002-05-02 19:56:55 +000030 if (len == 0) {
Guido van Rossum65e0b992001-01-15 18:58:56 +000031 start = 0;
32 len = 0;
33 step = 1;
Guido van Rossum65e0b992001-01-15 18:58:56 +000034 }
35 else {
36 long last = start + (len - 1) * step;
37 if ((step > 0) ?
Thomas Woutersefafcea2001-07-09 12:30:54 +000038 (last > (PyInt_GetMax() - step)) :
39 (last < (-1 - PyInt_GetMax() - step))) {
Guido van Rossum65e0b992001-01-15 18:58:56 +000040 PyErr_SetString(PyExc_OverflowError,
41 "integer addition");
42 return NULL;
Thomas Woutersefafcea2001-07-09 12:30:54 +000043 }
Guido van Rossum65e0b992001-01-15 18:58:56 +000044 }
Guido van Rossum12d12c51993-10-26 17:58:25 +000045 obj->start = start;
46 obj->len = len;
47 obj->step = step;
Martin v. Löwise4526592002-05-08 08:49:27 +000048 obj->index = 0;
49 obj->used = 0;
Guido van Rossum12d12c51993-10-26 17:58:25 +000050
Guido van Rossumc0b618a1997-05-02 03:12:38 +000051 return (PyObject *) obj;
Guido van Rossum12d12c51993-10-26 17:58:25 +000052}
53
Guido van Rossumc0b618a1997-05-02 03:12:38 +000054static PyObject *
Fred Drake45cfbcc2000-07-09 06:21:27 +000055range_item(rangeobject *r, int i)
Guido van Rossum12d12c51993-10-26 17:58:25 +000056{
Fred Draked9018322002-05-02 19:56:55 +000057 if (i < 0 || i >= r->len) {
58 PyErr_SetString(PyExc_IndexError,
Guido van Rossum5dadf7e1999-01-09 21:40:35 +000059 "xrange object index out of range");
Fred Draked9018322002-05-02 19:56:55 +000060 return NULL;
61 }
Guido van Rossumc0b618a1997-05-02 03:12:38 +000062 return PyInt_FromLong(r->start + (i % r->len) * r->step);
Guido van Rossum12d12c51993-10-26 17:58:25 +000063}
64
65static int
Fred Drake45cfbcc2000-07-09 06:21:27 +000066range_length(rangeobject *r)
Guido van Rossum12d12c51993-10-26 17:58:25 +000067{
Fred Draked9018322002-05-02 19:56:55 +000068 return r->len;
Guido van Rossum7d6aa511993-12-21 22:50:31 +000069}
70
Guido van Rossumc0b618a1997-05-02 03:12:38 +000071static PyObject *
Fred Drake45cfbcc2000-07-09 06:21:27 +000072range_repr(rangeobject *r)
Guido van Rossum12d12c51993-10-26 17:58:25 +000073{
Barry Warsaw7ce36942001-08-24 18:34:26 +000074 PyObject *rtn;
75
Tim Peters72d421b2000-08-04 03:05:40 +000076 if (r->start == 0 && r->step == 1)
Barry Warsaw7ce36942001-08-24 18:34:26 +000077 rtn = PyString_FromFormat("xrange(%ld)",
78 r->start + r->len * r->step);
Tim Peters72d421b2000-08-04 03:05:40 +000079
80 else if (r->step == 1)
Barry Warsaw7ce36942001-08-24 18:34:26 +000081 rtn = PyString_FromFormat("xrange(%ld, %ld)",
82 r->start,
83 r->start + r->len * r->step);
Tim Peters72d421b2000-08-04 03:05:40 +000084
85 else
Barry Warsaw7ce36942001-08-24 18:34:26 +000086 rtn = PyString_FromFormat("xrange(%ld, %ld, %ld)",
87 r->start,
88 r->start + r->len * r->step,
89 r->step);
Barry Warsaw7ce36942001-08-24 18:34:26 +000090 return rtn;
Thomas Woutersefafcea2001-07-09 12:30:54 +000091}
92
Martin v. Löwise4526592002-05-08 08:49:27 +000093static PyObject *
94range_getiter(rangeobject *r)
95{
96 rangeobject *obj;
97 if (r->used == 0 || r->index >= r->len) {
98 Py_INCREF(r);
99 r->used = 1;
100 r->index = 0;
101 return (PyObject *)r;
102 }
103
104 obj = PyObject_NEW(rangeobject, &PyRange_Type);
105 if (obj == NULL)
106 return NULL;
107
108 obj->start = r->start;
109 obj->len = r->len;
110 obj->step = r->step;
111 obj->index = 0;
112 obj->used = 1;
113 return (PyObject *) obj;
114}
115
116static PyObject *
117range_next(rangeobject *r)
118{
119 if (r->index >= r->len) {
120 PyErr_SetObject(PyExc_StopIteration, Py_None);
121 return NULL;
122 }
123 return PyInt_FromLong(r->start + (r->index++) * r->step);
124}
125
126static PyMethodDef range_methods[] = {
127 {"next", (PyCFunction)range_next, METH_NOARGS,
128 "it.next() -- get the next value, or raise StopIteration"},
129 {NULL, NULL} /* sentinel */
130};
131
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000132static PySequenceMethods range_as_sequence = {
Fred Draked9018322002-05-02 19:56:55 +0000133 (inquiry)range_length, /* sq_length */
134 0, /* sq_concat */
135 0, /* sq_repeat */
136 (intargfunc)range_item, /* sq_item */
137 0, /* sq_slice */
Guido van Rossum12d12c51993-10-26 17:58:25 +0000138};
139
Guido van Rossumc0b618a1997-05-02 03:12:38 +0000140PyTypeObject PyRange_Type = {
141 PyObject_HEAD_INIT(&PyType_Type)
Fred Draked9018322002-05-02 19:56:55 +0000142 0, /* Number of items for varobject */
143 "xrange", /* Name of this type */
144 sizeof(rangeobject), /* Basic object size */
145 0, /* Item size for varobject */
146 (destructor)PyObject_Del, /* tp_dealloc */
147 0, /* tp_print */
148 0, /* tp_getattr */
149 0, /* tp_setattr */
150 0, /* tp_compare */
151 (reprfunc)range_repr, /* tp_repr */
152 0, /* tp_as_number */
153 &range_as_sequence, /* tp_as_sequence */
154 0, /* tp_as_mapping */
155 0, /* tp_hash */
156 0, /* tp_call */
157 0, /* tp_str */
Martin v. Löwise4526592002-05-08 08:49:27 +0000158 PyObject_GenericGetAttr, /* tp_getattro */
Fred Draked9018322002-05-02 19:56:55 +0000159 0, /* tp_setattro */
160 0, /* tp_as_buffer */
161 Py_TPFLAGS_DEFAULT, /* tp_flags */
162 0, /* tp_doc */
Martin v. Löwise4526592002-05-08 08:49:27 +0000163 0, /* tp_traverse */
164 0, /* tp_clear */
165 0, /* tp_richcompare */
166 0, /* tp_weaklistoffset */
167 (getiterfunc)range_getiter, /* tp_iter */
168 (iternextfunc)range_next, /* tp_iternext */
169 range_methods, /* tp_methods */
Guido van Rossum12d12c51993-10-26 17:58:25 +0000170};