blob: c4f4e616b6279ec942bfbf68a0ffc2ea77284c47 [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;
Neil Schemenauer7eac9b72001-07-12 13:27:25 +000021 PyObject_GC_Init(it);
Guido van Rossum05311482001-04-20 21:06:46 +000022 return (PyObject *)it;
23}
24static void
Guido van Rossum213c7a62001-04-23 14:08:49 +000025iter_dealloc(seqiterobject *it)
Guido van Rossum05311482001-04-20 21:06:46 +000026{
Neil Schemenauer7eac9b72001-07-12 13:27:25 +000027 PyObject_GC_Fini(it);
Guido van Rossum05311482001-04-20 21:06:46 +000028 Py_DECREF(it->it_seq);
Neil Schemenauer7eac9b72001-07-12 13:27:25 +000029 it = (seqiterobject *) PyObject_AS_GC(it);
Guido van Rossum05311482001-04-20 21:06:46 +000030 PyObject_DEL(it);
31}
32
Neil Schemenauer7eac9b72001-07-12 13:27:25 +000033static int
34iter_traverse(seqiterobject *it, visitproc visit, void *arg)
35{
36 return visit(it->it_seq, arg);
37}
38
Guido van Rossum05311482001-04-20 21:06:46 +000039static PyObject *
Guido van Rossum213c7a62001-04-23 14:08:49 +000040iter_next(seqiterobject *it, PyObject *args)
Guido van Rossum05311482001-04-20 21:06:46 +000041{
42 PyObject *seq = it->it_seq;
Guido van Rossum213c7a62001-04-23 14:08:49 +000043 PyObject *result = PySequence_GetItem(seq, it->it_index++);
Guido van Rossum05311482001-04-20 21:06:46 +000044
Guido van Rossum213c7a62001-04-23 14:08:49 +000045 if (result == NULL && PyErr_ExceptionMatches(PyExc_IndexError))
46 PyErr_SetObject(PyExc_StopIteration, Py_None);
47 return result;
Guido van Rossum05311482001-04-20 21:06:46 +000048}
49
50static PyObject *
51iter_getiter(PyObject *it)
52{
53 Py_INCREF(it);
54 return it;
55}
56
Guido van Rossum213c7a62001-04-23 14:08:49 +000057static PyObject *
58iter_iternext(PyObject *iterator)
59{
60 seqiterobject *it;
61 PyObject *seq;
62
63 assert(PySeqIter_Check(iterator));
64 it = (seqiterobject *)iterator;
65 seq = it->it_seq;
66
67 if (PyList_Check(seq)) {
68 PyObject *item;
69 if (it->it_index >= PyList_GET_SIZE(seq)) {
70 return NULL;
71 }
72 item = PyList_GET_ITEM(seq, it->it_index);
73 it->it_index++;
74 Py_INCREF(item);
75 return item;
76 }
77 else {
78 PyObject *result = PySequence_GetItem(seq, it->it_index++);
79 if (result != NULL) {
80 return result;
81 }
82 if (PyErr_ExceptionMatches(PyExc_IndexError) ||
83 PyErr_ExceptionMatches(PyExc_StopIteration)) {
84 PyErr_Clear();
85 return NULL;
86 }
87 else {
88 return NULL;
89 }
90 }
91}
92
Guido van Rossum05311482001-04-20 21:06:46 +000093static PyMethodDef iter_methods[] = {
94 {"next", (PyCFunction)iter_next, METH_VARARGS,
95 "it.next() -- get the next value, or raise StopIteration"},
96 {NULL, NULL} /* sentinel */
97};
98
99static PyObject *
Guido van Rossum213c7a62001-04-23 14:08:49 +0000100iter_getattr(seqiterobject *it, char *name)
Guido van Rossum05311482001-04-20 21:06:46 +0000101{
102 return Py_FindMethod(iter_methods, (PyObject *)it, name);
103}
104
Guido van Rossum213c7a62001-04-23 14:08:49 +0000105PyTypeObject PySeqIter_Type = {
Guido van Rossum05311482001-04-20 21:06:46 +0000106 PyObject_HEAD_INIT(&PyType_Type)
107 0, /* ob_size */
108 "iterator", /* tp_name */
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000109 sizeof(seqiterobject) + PyGC_HEAD_SIZE, /* tp_basicsize */
Guido van Rossum05311482001-04-20 21:06:46 +0000110 0, /* tp_itemsize */
111 /* methods */
112 (destructor)iter_dealloc, /* tp_dealloc */
113 0, /* tp_print */
114 (getattrfunc)iter_getattr, /* tp_getattr */
115 0, /* tp_setattr */
116 0, /* tp_compare */
117 0, /* tp_repr */
118 0, /* tp_as_number */
119 0, /* tp_as_sequence */
120 0, /* tp_as_mapping */
121 0, /* tp_hash */
122 0, /* tp_call */
123 0, /* tp_str */
124 0, /* tp_getattro */
125 0, /* tp_setattro */
126 0, /* tp_as_buffer */
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000127 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */
Guido van Rossum05311482001-04-20 21:06:46 +0000128 0, /* tp_doc */
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000129 (traverseproc)iter_traverse, /* tp_traverse */
Guido van Rossum05311482001-04-20 21:06:46 +0000130 0, /* tp_clear */
131 0, /* tp_richcompare */
132 0, /* tp_weaklistoffset */
133 (getiterfunc)iter_getiter, /* tp_iter */
Guido van Rossum213c7a62001-04-23 14:08:49 +0000134 (iternextfunc)iter_iternext, /* tp_iternext */
Guido van Rossum05311482001-04-20 21:06:46 +0000135};
136
137/* -------------------------------------- */
138
139typedef struct {
140 PyObject_HEAD
141 PyObject *it_callable;
142 PyObject *it_sentinel;
143} calliterobject;
144
145PyObject *
146PyCallIter_New(PyObject *callable, PyObject *sentinel)
147{
148 calliterobject *it;
149 it = PyObject_NEW(calliterobject, &PyCallIter_Type);
150 if (it == NULL)
151 return NULL;
152 Py_INCREF(callable);
153 it->it_callable = callable;
154 Py_INCREF(sentinel);
155 it->it_sentinel = sentinel;
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000156 PyObject_GC_Init(it);
Guido van Rossum05311482001-04-20 21:06:46 +0000157 return (PyObject *)it;
158}
159static void
160calliter_dealloc(calliterobject *it)
161{
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000162 PyObject_GC_Fini(it);
Guido van Rossum05311482001-04-20 21:06:46 +0000163 Py_DECREF(it->it_callable);
164 Py_DECREF(it->it_sentinel);
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000165 it = (calliterobject *) PyObject_AS_GC(it);
Guido van Rossum05311482001-04-20 21:06:46 +0000166 PyObject_DEL(it);
167}
Guido van Rossum213c7a62001-04-23 14:08:49 +0000168
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000169static int
170calliter_traverse(calliterobject *it, visitproc visit, void *arg)
171{
172 int err;
173 if ((err = visit(it->it_callable, arg)))
174 return err;
175 if ((err = visit(it->it_sentinel, arg)))
176 return err;
177 return 0;
178}
179
Guido van Rossum05311482001-04-20 21:06:46 +0000180static PyObject *
181calliter_next(calliterobject *it, PyObject *args)
182{
183 PyObject *result = PyObject_CallObject(it->it_callable, NULL);
184 if (result != NULL) {
185 if (PyObject_RichCompareBool(result, it->it_sentinel, Py_EQ)) {
186 PyErr_SetObject(PyExc_StopIteration, Py_None);
187 Py_DECREF(result);
188 result = NULL;
189 }
190 }
191 return result;
192}
193
194static PyMethodDef calliter_methods[] = {
195 {"next", (PyCFunction)calliter_next, METH_VARARGS,
196 "it.next() -- get the next value, or raise StopIteration"},
197 {NULL, NULL} /* sentinel */
198};
199
200static PyObject *
201calliter_getattr(calliterobject *it, char *name)
202{
203 return Py_FindMethod(calliter_methods, (PyObject *)it, name);
204}
205
Guido van Rossum213c7a62001-04-23 14:08:49 +0000206static PyObject *
207calliter_iternext(calliterobject *it)
208{
209 PyObject *result = PyObject_CallObject(it->it_callable, NULL);
210 if (result != NULL) {
211 if (PyObject_RichCompareBool(result, it->it_sentinel, Py_EQ)) {
212 Py_DECREF(result);
213 result = NULL;
214 }
215 }
216 else if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
217 PyErr_Clear();
218 }
219 return result;
220}
221
Guido van Rossum05311482001-04-20 21:06:46 +0000222PyTypeObject PyCallIter_Type = {
223 PyObject_HEAD_INIT(&PyType_Type)
224 0, /* ob_size */
225 "callable-iterator", /* tp_name */
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000226 sizeof(calliterobject) + PyGC_HEAD_SIZE,/* tp_basicsize */
Guido van Rossum05311482001-04-20 21:06:46 +0000227 0, /* tp_itemsize */
228 /* methods */
229 (destructor)calliter_dealloc, /* tp_dealloc */
230 0, /* tp_print */
231 (getattrfunc)calliter_getattr, /* tp_getattr */
232 0, /* tp_setattr */
233 0, /* tp_compare */
234 0, /* tp_repr */
235 0, /* tp_as_number */
236 0, /* tp_as_sequence */
237 0, /* tp_as_mapping */
238 0, /* tp_hash */
239 0, /* tp_call */
240 0, /* tp_str */
241 0, /* tp_getattro */
242 0, /* tp_setattro */
243 0, /* tp_as_buffer */
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000244 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */
Guido van Rossum05311482001-04-20 21:06:46 +0000245 0, /* tp_doc */
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000246 (traverseproc)calliter_traverse, /* tp_traverse */
Guido van Rossum05311482001-04-20 21:06:46 +0000247 0, /* tp_clear */
248 0, /* tp_richcompare */
249 0, /* tp_weaklistoffset */
250 (getiterfunc)iter_getiter, /* tp_iter */
Guido van Rossum213c7a62001-04-23 14:08:49 +0000251 (iternextfunc)calliter_iternext, /* tp_iternext */
Guido van Rossum05311482001-04-20 21:06:46 +0000252};