blob: ce1fe3dc89d969f3e44c1885e85bcda433243786 [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;
Martin v. Löwis01f94bd2002-05-08 08:44:21 +000015
16 if (!PySequence_Check(seq)) {
17 PyErr_BadInternalCall();
18 return NULL;
19 }
Neil Schemenauerdbf409f2002-03-18 20:43:51 +000020 it = PyObject_GC_New(seqiterobject, &PySeqIter_Type);
Guido van Rossum05311482001-04-20 21:06:46 +000021 if (it == NULL)
22 return NULL;
23 it->it_index = 0;
24 Py_INCREF(seq);
25 it->it_seq = seq;
Neil Schemenauerdbf409f2002-03-18 20:43:51 +000026 _PyObject_GC_TRACK(it);
Guido van Rossum05311482001-04-20 21:06:46 +000027 return (PyObject *)it;
28}
29static void
Guido van Rossum213c7a62001-04-23 14:08:49 +000030iter_dealloc(seqiterobject *it)
Guido van Rossum05311482001-04-20 21:06:46 +000031{
Neil Schemenauerdbf409f2002-03-18 20:43:51 +000032 _PyObject_GC_UNTRACK(it);
Guido van Rossum05311482001-04-20 21:06:46 +000033 Py_DECREF(it->it_seq);
Neil Schemenauerdbf409f2002-03-18 20:43:51 +000034 PyObject_GC_Del(it);
Guido van Rossum05311482001-04-20 21:06:46 +000035}
36
Neil Schemenauer7eac9b72001-07-12 13:27:25 +000037static int
38iter_traverse(seqiterobject *it, visitproc visit, void *arg)
39{
40 return visit(it->it_seq, arg);
41}
42
Guido van Rossum05311482001-04-20 21:06:46 +000043static PyObject *
Martin v. Löwise3eb1f22001-08-16 13:15:00 +000044iter_next(seqiterobject *it)
Guido van Rossum05311482001-04-20 21:06:46 +000045{
46 PyObject *seq = it->it_seq;
Guido van Rossum213c7a62001-04-23 14:08:49 +000047 PyObject *result = PySequence_GetItem(seq, it->it_index++);
Guido van Rossum05311482001-04-20 21:06:46 +000048
Guido van Rossum213c7a62001-04-23 14:08:49 +000049 if (result == NULL && PyErr_ExceptionMatches(PyExc_IndexError))
50 PyErr_SetObject(PyExc_StopIteration, Py_None);
51 return result;
Guido van Rossum05311482001-04-20 21:06:46 +000052}
53
54static PyObject *
55iter_getiter(PyObject *it)
56{
57 Py_INCREF(it);
58 return it;
59}
60
Guido van Rossum213c7a62001-04-23 14:08:49 +000061static PyObject *
62iter_iternext(PyObject *iterator)
63{
64 seqiterobject *it;
65 PyObject *seq;
66
67 assert(PySeqIter_Check(iterator));
68 it = (seqiterobject *)iterator;
69 seq = it->it_seq;
70
Martin v. Löwis01f94bd2002-05-08 08:44:21 +000071 if (PyTuple_CheckExact(seq)) {
Raymond Hettinger14bd6de2002-05-31 21:40:38 +000072 if (it->it_index < PyTuple_GET_SIZE(seq)) {
73 PyObject *item;
74 item = PyTuple_GET_ITEM(seq, it->it_index);
75 it->it_index++;
76 Py_INCREF(item);
77 return item;
Martin v. Löwis01f94bd2002-05-08 08:44:21 +000078 }
Raymond Hettinger14bd6de2002-05-31 21:40:38 +000079 return NULL;
Martin v. Löwis01f94bd2002-05-08 08:44:21 +000080 }
Guido van Rossum213c7a62001-04-23 14:08:49 +000081 else {
Martin v. Löwis01f94bd2002-05-08 08:44:21 +000082 PyObject *result = PySequence_ITEM(seq, it->it_index);
83 it->it_index++;
Guido van Rossum213c7a62001-04-23 14:08:49 +000084 if (result != NULL) {
85 return result;
86 }
87 if (PyErr_ExceptionMatches(PyExc_IndexError) ||
88 PyErr_ExceptionMatches(PyExc_StopIteration)) {
89 PyErr_Clear();
90 return NULL;
91 }
92 else {
93 return NULL;
94 }
95 }
96}
97
Guido van Rossum05311482001-04-20 21:06:46 +000098static PyMethodDef iter_methods[] = {
Martin v. Löwise3eb1f22001-08-16 13:15:00 +000099 {"next", (PyCFunction)iter_next, METH_NOARGS,
Guido van Rossum05311482001-04-20 21:06:46 +0000100 "it.next() -- get the next value, or raise StopIteration"},
101 {NULL, NULL} /* sentinel */
102};
103
Guido van Rossum213c7a62001-04-23 14:08:49 +0000104PyTypeObject PySeqIter_Type = {
Guido van Rossum05311482001-04-20 21:06:46 +0000105 PyObject_HEAD_INIT(&PyType_Type)
106 0, /* ob_size */
107 "iterator", /* tp_name */
Neil Schemenauerdbf409f2002-03-18 20:43:51 +0000108 sizeof(seqiterobject), /* tp_basicsize */
Guido van Rossum05311482001-04-20 21:06:46 +0000109 0, /* tp_itemsize */
110 /* methods */
111 (destructor)iter_dealloc, /* tp_dealloc */
112 0, /* tp_print */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000113 0, /* tp_getattr */
Guido van Rossum05311482001-04-20 21:06:46 +0000114 0, /* tp_setattr */
115 0, /* tp_compare */
116 0, /* tp_repr */
117 0, /* tp_as_number */
118 0, /* tp_as_sequence */
119 0, /* tp_as_mapping */
120 0, /* tp_hash */
121 0, /* tp_call */
122 0, /* tp_str */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000123 PyObject_GenericGetAttr, /* tp_getattro */
Guido van Rossum05311482001-04-20 21:06:46 +0000124 0, /* tp_setattro */
125 0, /* tp_as_buffer */
Neil Schemenauerdbf409f2002-03-18 20:43:51 +0000126 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
Guido van Rossum05311482001-04-20 21:06:46 +0000127 0, /* tp_doc */
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000128 (traverseproc)iter_traverse, /* tp_traverse */
Guido van Rossum05311482001-04-20 21:06:46 +0000129 0, /* tp_clear */
130 0, /* tp_richcompare */
131 0, /* tp_weaklistoffset */
132 (getiterfunc)iter_getiter, /* tp_iter */
Guido van Rossum213c7a62001-04-23 14:08:49 +0000133 (iternextfunc)iter_iternext, /* tp_iternext */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000134 iter_methods, /* tp_methods */
135 0, /* tp_members */
136 0, /* tp_getset */
137 0, /* tp_base */
138 0, /* tp_dict */
139 0, /* tp_descr_get */
140 0, /* tp_descr_set */
Guido van Rossum05311482001-04-20 21:06:46 +0000141};
142
143/* -------------------------------------- */
144
145typedef struct {
146 PyObject_HEAD
147 PyObject *it_callable;
148 PyObject *it_sentinel;
149} calliterobject;
150
151PyObject *
152PyCallIter_New(PyObject *callable, PyObject *sentinel)
153{
154 calliterobject *it;
Neil Schemenauerdbf409f2002-03-18 20:43:51 +0000155 it = PyObject_GC_New(calliterobject, &PyCallIter_Type);
Guido van Rossum05311482001-04-20 21:06:46 +0000156 if (it == NULL)
157 return NULL;
158 Py_INCREF(callable);
159 it->it_callable = callable;
160 Py_INCREF(sentinel);
161 it->it_sentinel = sentinel;
Neil Schemenauerdbf409f2002-03-18 20:43:51 +0000162 _PyObject_GC_TRACK(it);
Guido van Rossum05311482001-04-20 21:06:46 +0000163 return (PyObject *)it;
164}
165static void
166calliter_dealloc(calliterobject *it)
167{
Neil Schemenauerdbf409f2002-03-18 20:43:51 +0000168 _PyObject_GC_UNTRACK(it);
Guido van Rossum05311482001-04-20 21:06:46 +0000169 Py_DECREF(it->it_callable);
170 Py_DECREF(it->it_sentinel);
Neil Schemenauerdbf409f2002-03-18 20:43:51 +0000171 PyObject_GC_Del(it);
Guido van Rossum05311482001-04-20 21:06:46 +0000172}
Guido van Rossum213c7a62001-04-23 14:08:49 +0000173
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000174static int
175calliter_traverse(calliterobject *it, visitproc visit, void *arg)
176{
177 int err;
178 if ((err = visit(it->it_callable, arg)))
179 return err;
180 if ((err = visit(it->it_sentinel, arg)))
181 return err;
182 return 0;
183}
184
Guido van Rossum05311482001-04-20 21:06:46 +0000185static PyObject *
186calliter_next(calliterobject *it, PyObject *args)
187{
188 PyObject *result = PyObject_CallObject(it->it_callable, NULL);
189 if (result != NULL) {
190 if (PyObject_RichCompareBool(result, it->it_sentinel, Py_EQ)) {
191 PyErr_SetObject(PyExc_StopIteration, Py_None);
192 Py_DECREF(result);
193 result = NULL;
194 }
195 }
196 return result;
197}
198
199static PyMethodDef calliter_methods[] = {
200 {"next", (PyCFunction)calliter_next, METH_VARARGS,
201 "it.next() -- get the next value, or raise StopIteration"},
202 {NULL, NULL} /* sentinel */
203};
204
205static PyObject *
Guido van Rossum213c7a62001-04-23 14:08:49 +0000206calliter_iternext(calliterobject *it)
207{
208 PyObject *result = PyObject_CallObject(it->it_callable, NULL);
209 if (result != NULL) {
210 if (PyObject_RichCompareBool(result, it->it_sentinel, Py_EQ)) {
211 Py_DECREF(result);
212 result = NULL;
213 }
214 }
215 else if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
216 PyErr_Clear();
217 }
218 return result;
219}
220
Guido van Rossum05311482001-04-20 21:06:46 +0000221PyTypeObject PyCallIter_Type = {
222 PyObject_HEAD_INIT(&PyType_Type)
223 0, /* ob_size */
224 "callable-iterator", /* tp_name */
Neil Schemenauerdbf409f2002-03-18 20:43:51 +0000225 sizeof(calliterobject), /* tp_basicsize */
Guido van Rossum05311482001-04-20 21:06:46 +0000226 0, /* tp_itemsize */
227 /* methods */
228 (destructor)calliter_dealloc, /* tp_dealloc */
229 0, /* tp_print */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000230 0, /* tp_getattr */
Guido van Rossum05311482001-04-20 21:06:46 +0000231 0, /* tp_setattr */
232 0, /* tp_compare */
233 0, /* tp_repr */
234 0, /* tp_as_number */
235 0, /* tp_as_sequence */
236 0, /* tp_as_mapping */
237 0, /* tp_hash */
238 0, /* tp_call */
239 0, /* tp_str */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000240 PyObject_GenericGetAttr, /* tp_getattro */
Guido van Rossum05311482001-04-20 21:06:46 +0000241 0, /* tp_setattro */
242 0, /* tp_as_buffer */
Neil Schemenauerdbf409f2002-03-18 20:43:51 +0000243 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
Guido van Rossum05311482001-04-20 21:06:46 +0000244 0, /* tp_doc */
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000245 (traverseproc)calliter_traverse, /* tp_traverse */
Guido van Rossum05311482001-04-20 21:06:46 +0000246 0, /* tp_clear */
247 0, /* tp_richcompare */
248 0, /* tp_weaklistoffset */
249 (getiterfunc)iter_getiter, /* tp_iter */
Guido van Rossum213c7a62001-04-23 14:08:49 +0000250 (iternextfunc)calliter_iternext, /* tp_iternext */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000251 calliter_methods, /* tp_methods */
252 0, /* tp_members */
253 0, /* tp_getset */
254 0, /* tp_base */
255 0, /* tp_dict */
256 0, /* tp_descr_get */
257 0, /* tp_descr_set */
Guido van Rossum05311482001-04-20 21:06:46 +0000258};