blob: 6a11772377e63ffc702c518d51f2c61db5a37dae [file] [log] [blame]
Guido van Rossum05311482001-04-20 21:06:46 +00001/* Iterator objects */
2
3#include "Python.h"
4
5typedef struct {
6 PyObject_HEAD
7 long it_index;
8 PyObject *it_seq;
Guido van Rossum213c7a62001-04-23 14:08:49 +00009} seqiterobject;
Guido van Rossum05311482001-04-20 21:06:46 +000010
11PyObject *
Guido van Rossum213c7a62001-04-23 14:08:49 +000012PySeqIter_New(PyObject *seq)
Guido van Rossum05311482001-04-20 21:06:46 +000013{
Guido van Rossum213c7a62001-04-23 14:08:49 +000014 seqiterobject *it;
15 it = PyObject_NEW(seqiterobject, &PySeqIter_Type);
Guido van Rossum05311482001-04-20 21:06:46 +000016 if (it == NULL)
17 return NULL;
18 it->it_index = 0;
19 Py_INCREF(seq);
20 it->it_seq = seq;
21 return (PyObject *)it;
22}
23static void
Guido van Rossum213c7a62001-04-23 14:08:49 +000024iter_dealloc(seqiterobject *it)
Guido van Rossum05311482001-04-20 21:06:46 +000025{
26 Py_DECREF(it->it_seq);
27 PyObject_DEL(it);
28}
29
30static PyObject *
Guido van Rossum213c7a62001-04-23 14:08:49 +000031iter_next(seqiterobject *it, PyObject *args)
Guido van Rossum05311482001-04-20 21:06:46 +000032{
33 PyObject *seq = it->it_seq;
Guido van Rossum213c7a62001-04-23 14:08:49 +000034 PyObject *result = PySequence_GetItem(seq, it->it_index++);
Guido van Rossum05311482001-04-20 21:06:46 +000035
Guido van Rossum213c7a62001-04-23 14:08:49 +000036 if (result == NULL && PyErr_ExceptionMatches(PyExc_IndexError))
37 PyErr_SetObject(PyExc_StopIteration, Py_None);
38 return result;
Guido van Rossum05311482001-04-20 21:06:46 +000039}
40
41static PyObject *
42iter_getiter(PyObject *it)
43{
44 Py_INCREF(it);
45 return it;
46}
47
Guido van Rossum213c7a62001-04-23 14:08:49 +000048static PyObject *
49iter_iternext(PyObject *iterator)
50{
51 seqiterobject *it;
52 PyObject *seq;
53
54 assert(PySeqIter_Check(iterator));
55 it = (seqiterobject *)iterator;
56 seq = it->it_seq;
57
58 if (PyList_Check(seq)) {
59 PyObject *item;
60 if (it->it_index >= PyList_GET_SIZE(seq)) {
61 return NULL;
62 }
63 item = PyList_GET_ITEM(seq, it->it_index);
64 it->it_index++;
65 Py_INCREF(item);
66 return item;
67 }
68 else {
69 PyObject *result = PySequence_GetItem(seq, it->it_index++);
70 if (result != NULL) {
71 return result;
72 }
73 if (PyErr_ExceptionMatches(PyExc_IndexError) ||
74 PyErr_ExceptionMatches(PyExc_StopIteration)) {
75 PyErr_Clear();
76 return NULL;
77 }
78 else {
79 return NULL;
80 }
81 }
82}
83
Guido van Rossum05311482001-04-20 21:06:46 +000084static PyMethodDef iter_methods[] = {
85 {"next", (PyCFunction)iter_next, METH_VARARGS,
86 "it.next() -- get the next value, or raise StopIteration"},
87 {NULL, NULL} /* sentinel */
88};
89
90static PyObject *
Guido van Rossum213c7a62001-04-23 14:08:49 +000091iter_getattr(seqiterobject *it, char *name)
Guido van Rossum05311482001-04-20 21:06:46 +000092{
93 return Py_FindMethod(iter_methods, (PyObject *)it, name);
94}
95
Guido van Rossum213c7a62001-04-23 14:08:49 +000096PyTypeObject PySeqIter_Type = {
Guido van Rossum05311482001-04-20 21:06:46 +000097 PyObject_HEAD_INIT(&PyType_Type)
98 0, /* ob_size */
99 "iterator", /* tp_name */
Guido van Rossum213c7a62001-04-23 14:08:49 +0000100 sizeof(seqiterobject), /* tp_basicsize */
Guido van Rossum05311482001-04-20 21:06:46 +0000101 0, /* tp_itemsize */
102 /* methods */
103 (destructor)iter_dealloc, /* tp_dealloc */
104 0, /* tp_print */
105 (getattrfunc)iter_getattr, /* tp_getattr */
106 0, /* tp_setattr */
107 0, /* tp_compare */
108 0, /* tp_repr */
109 0, /* tp_as_number */
110 0, /* tp_as_sequence */
111 0, /* tp_as_mapping */
112 0, /* tp_hash */
113 0, /* tp_call */
114 0, /* tp_str */
115 0, /* tp_getattro */
116 0, /* tp_setattro */
117 0, /* tp_as_buffer */
118 Py_TPFLAGS_DEFAULT, /* tp_flags */
119 0, /* tp_doc */
120 0, /* tp_traverse */
121 0, /* tp_clear */
122 0, /* tp_richcompare */
123 0, /* tp_weaklistoffset */
124 (getiterfunc)iter_getiter, /* tp_iter */
Guido van Rossum213c7a62001-04-23 14:08:49 +0000125 (iternextfunc)iter_iternext, /* tp_iternext */
Guido van Rossum05311482001-04-20 21:06:46 +0000126};
127
128/* -------------------------------------- */
129
130typedef struct {
131 PyObject_HEAD
132 PyObject *it_callable;
133 PyObject *it_sentinel;
134} calliterobject;
135
136PyObject *
137PyCallIter_New(PyObject *callable, PyObject *sentinel)
138{
139 calliterobject *it;
140 it = PyObject_NEW(calliterobject, &PyCallIter_Type);
141 if (it == NULL)
142 return NULL;
143 Py_INCREF(callable);
144 it->it_callable = callable;
145 Py_INCREF(sentinel);
146 it->it_sentinel = sentinel;
147 return (PyObject *)it;
148}
149static void
150calliter_dealloc(calliterobject *it)
151{
152 Py_DECREF(it->it_callable);
153 Py_DECREF(it->it_sentinel);
154 PyObject_DEL(it);
155}
Guido van Rossum213c7a62001-04-23 14:08:49 +0000156
Guido van Rossum05311482001-04-20 21:06:46 +0000157static PyObject *
158calliter_next(calliterobject *it, PyObject *args)
159{
160 PyObject *result = PyObject_CallObject(it->it_callable, NULL);
161 if (result != NULL) {
162 if (PyObject_RichCompareBool(result, it->it_sentinel, Py_EQ)) {
163 PyErr_SetObject(PyExc_StopIteration, Py_None);
164 Py_DECREF(result);
165 result = NULL;
166 }
167 }
168 return result;
169}
170
171static PyMethodDef calliter_methods[] = {
172 {"next", (PyCFunction)calliter_next, METH_VARARGS,
173 "it.next() -- get the next value, or raise StopIteration"},
174 {NULL, NULL} /* sentinel */
175};
176
177static PyObject *
178calliter_getattr(calliterobject *it, char *name)
179{
180 return Py_FindMethod(calliter_methods, (PyObject *)it, name);
181}
182
Guido van Rossum213c7a62001-04-23 14:08:49 +0000183static PyObject *
184calliter_iternext(calliterobject *it)
185{
186 PyObject *result = PyObject_CallObject(it->it_callable, NULL);
187 if (result != NULL) {
188 if (PyObject_RichCompareBool(result, it->it_sentinel, Py_EQ)) {
189 Py_DECREF(result);
190 result = NULL;
191 }
192 }
193 else if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
194 PyErr_Clear();
195 }
196 return result;
197}
198
Guido van Rossum05311482001-04-20 21:06:46 +0000199PyTypeObject PyCallIter_Type = {
200 PyObject_HEAD_INIT(&PyType_Type)
201 0, /* ob_size */
202 "callable-iterator", /* tp_name */
203 sizeof(calliterobject), /* tp_basicsize */
204 0, /* tp_itemsize */
205 /* methods */
206 (destructor)calliter_dealloc, /* tp_dealloc */
207 0, /* tp_print */
208 (getattrfunc)calliter_getattr, /* tp_getattr */
209 0, /* tp_setattr */
210 0, /* tp_compare */
211 0, /* tp_repr */
212 0, /* tp_as_number */
213 0, /* tp_as_sequence */
214 0, /* tp_as_mapping */
215 0, /* tp_hash */
216 0, /* tp_call */
217 0, /* tp_str */
218 0, /* tp_getattro */
219 0, /* tp_setattro */
220 0, /* tp_as_buffer */
221 Py_TPFLAGS_DEFAULT, /* tp_flags */
222 0, /* tp_doc */
223 0, /* tp_traverse */
224 0, /* tp_clear */
225 0, /* tp_richcompare */
226 0, /* tp_weaklistoffset */
227 (getiterfunc)iter_getiter, /* tp_iter */
Guido van Rossum213c7a62001-04-23 14:08:49 +0000228 (iternextfunc)calliter_iternext, /* tp_iternext */
Guido van Rossum05311482001-04-20 21:06:46 +0000229};