blob: 789eb6c6890979a36454b6a2d19b806306eb3c40 [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;
Neil Schemenauerdbf409f2002-03-18 20:43:51 +000015 it = PyObject_GC_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 Schemenauerdbf409f2002-03-18 20:43:51 +000021 _PyObject_GC_TRACK(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 Schemenauerdbf409f2002-03-18 20:43:51 +000027 _PyObject_GC_UNTRACK(it);
Guido van Rossum05311482001-04-20 21:06:46 +000028 Py_DECREF(it->it_seq);
Neil Schemenauerdbf409f2002-03-18 20:43:51 +000029 PyObject_GC_Del(it);
Guido van Rossum05311482001-04-20 21:06:46 +000030}
31
Neil Schemenauer7eac9b72001-07-12 13:27:25 +000032static int
33iter_traverse(seqiterobject *it, visitproc visit, void *arg)
34{
35 return visit(it->it_seq, arg);
36}
37
Guido van Rossum05311482001-04-20 21:06:46 +000038static PyObject *
Martin v. Löwise3eb1f22001-08-16 13:15:00 +000039iter_next(seqiterobject *it)
Guido van Rossum05311482001-04-20 21:06:46 +000040{
41 PyObject *seq = it->it_seq;
Guido van Rossum213c7a62001-04-23 14:08:49 +000042 PyObject *result = PySequence_GetItem(seq, it->it_index++);
Guido van Rossum05311482001-04-20 21:06:46 +000043
Guido van Rossum213c7a62001-04-23 14:08:49 +000044 if (result == NULL && PyErr_ExceptionMatches(PyExc_IndexError))
45 PyErr_SetObject(PyExc_StopIteration, Py_None);
46 return result;
Guido van Rossum05311482001-04-20 21:06:46 +000047}
48
49static PyObject *
50iter_getiter(PyObject *it)
51{
52 Py_INCREF(it);
53 return it;
54}
55
Guido van Rossum213c7a62001-04-23 14:08:49 +000056static PyObject *
57iter_iternext(PyObject *iterator)
58{
59 seqiterobject *it;
60 PyObject *seq;
61
62 assert(PySeqIter_Check(iterator));
63 it = (seqiterobject *)iterator;
64 seq = it->it_seq;
65
66 if (PyList_Check(seq)) {
67 PyObject *item;
68 if (it->it_index >= PyList_GET_SIZE(seq)) {
69 return NULL;
70 }
71 item = PyList_GET_ITEM(seq, it->it_index);
72 it->it_index++;
73 Py_INCREF(item);
74 return item;
75 }
76 else {
77 PyObject *result = PySequence_GetItem(seq, it->it_index++);
78 if (result != NULL) {
79 return result;
80 }
81 if (PyErr_ExceptionMatches(PyExc_IndexError) ||
82 PyErr_ExceptionMatches(PyExc_StopIteration)) {
83 PyErr_Clear();
84 return NULL;
85 }
86 else {
87 return NULL;
88 }
89 }
90}
91
Guido van Rossum05311482001-04-20 21:06:46 +000092static PyMethodDef iter_methods[] = {
Martin v. Löwise3eb1f22001-08-16 13:15:00 +000093 {"next", (PyCFunction)iter_next, METH_NOARGS,
Guido van Rossum05311482001-04-20 21:06:46 +000094 "it.next() -- get the next value, or raise StopIteration"},
95 {NULL, NULL} /* sentinel */
96};
97
Guido van Rossum213c7a62001-04-23 14:08:49 +000098PyTypeObject PySeqIter_Type = {
Guido van Rossum05311482001-04-20 21:06:46 +000099 PyObject_HEAD_INIT(&PyType_Type)
100 0, /* ob_size */
101 "iterator", /* tp_name */
Neil Schemenauerdbf409f2002-03-18 20:43:51 +0000102 sizeof(seqiterobject), /* tp_basicsize */
Guido van Rossum05311482001-04-20 21:06:46 +0000103 0, /* tp_itemsize */
104 /* methods */
105 (destructor)iter_dealloc, /* tp_dealloc */
106 0, /* tp_print */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000107 0, /* tp_getattr */
Guido van Rossum05311482001-04-20 21:06:46 +0000108 0, /* tp_setattr */
109 0, /* tp_compare */
110 0, /* tp_repr */
111 0, /* tp_as_number */
112 0, /* tp_as_sequence */
113 0, /* tp_as_mapping */
114 0, /* tp_hash */
115 0, /* tp_call */
116 0, /* tp_str */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000117 PyObject_GenericGetAttr, /* tp_getattro */
Guido van Rossum05311482001-04-20 21:06:46 +0000118 0, /* tp_setattro */
119 0, /* tp_as_buffer */
Neil Schemenauerdbf409f2002-03-18 20:43:51 +0000120 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
Guido van Rossum05311482001-04-20 21:06:46 +0000121 0, /* tp_doc */
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000122 (traverseproc)iter_traverse, /* tp_traverse */
Guido van Rossum05311482001-04-20 21:06:46 +0000123 0, /* tp_clear */
124 0, /* tp_richcompare */
125 0, /* tp_weaklistoffset */
126 (getiterfunc)iter_getiter, /* tp_iter */
Guido van Rossum213c7a62001-04-23 14:08:49 +0000127 (iternextfunc)iter_iternext, /* tp_iternext */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000128 iter_methods, /* tp_methods */
129 0, /* tp_members */
130 0, /* tp_getset */
131 0, /* tp_base */
132 0, /* tp_dict */
133 0, /* tp_descr_get */
134 0, /* tp_descr_set */
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;
Neil Schemenauerdbf409f2002-03-18 20:43:51 +0000149 it = PyObject_GC_New(calliterobject, &PyCallIter_Type);
Guido van Rossum05311482001-04-20 21:06:46 +0000150 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 Schemenauerdbf409f2002-03-18 20:43:51 +0000156 _PyObject_GC_TRACK(it);
Guido van Rossum05311482001-04-20 21:06:46 +0000157 return (PyObject *)it;
158}
159static void
160calliter_dealloc(calliterobject *it)
161{
Neil Schemenauerdbf409f2002-03-18 20:43:51 +0000162 _PyObject_GC_UNTRACK(it);
Guido van Rossum05311482001-04-20 21:06:46 +0000163 Py_DECREF(it->it_callable);
164 Py_DECREF(it->it_sentinel);
Neil Schemenauerdbf409f2002-03-18 20:43:51 +0000165 PyObject_GC_Del(it);
Guido van Rossum05311482001-04-20 21:06:46 +0000166}
Guido van Rossum213c7a62001-04-23 14:08:49 +0000167
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000168static int
169calliter_traverse(calliterobject *it, visitproc visit, void *arg)
170{
171 int err;
172 if ((err = visit(it->it_callable, arg)))
173 return err;
174 if ((err = visit(it->it_sentinel, arg)))
175 return err;
176 return 0;
177}
178
Guido van Rossum05311482001-04-20 21:06:46 +0000179static PyObject *
180calliter_next(calliterobject *it, PyObject *args)
181{
182 PyObject *result = PyObject_CallObject(it->it_callable, NULL);
183 if (result != NULL) {
184 if (PyObject_RichCompareBool(result, it->it_sentinel, Py_EQ)) {
185 PyErr_SetObject(PyExc_StopIteration, Py_None);
186 Py_DECREF(result);
187 result = NULL;
188 }
189 }
190 return result;
191}
192
193static PyMethodDef calliter_methods[] = {
194 {"next", (PyCFunction)calliter_next, METH_VARARGS,
195 "it.next() -- get the next value, or raise StopIteration"},
196 {NULL, NULL} /* sentinel */
197};
198
199static PyObject *
Guido van Rossum213c7a62001-04-23 14:08:49 +0000200calliter_iternext(calliterobject *it)
201{
202 PyObject *result = PyObject_CallObject(it->it_callable, NULL);
203 if (result != NULL) {
204 if (PyObject_RichCompareBool(result, it->it_sentinel, Py_EQ)) {
205 Py_DECREF(result);
206 result = NULL;
207 }
208 }
209 else if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
210 PyErr_Clear();
211 }
212 return result;
213}
214
Guido van Rossum05311482001-04-20 21:06:46 +0000215PyTypeObject PyCallIter_Type = {
216 PyObject_HEAD_INIT(&PyType_Type)
217 0, /* ob_size */
218 "callable-iterator", /* tp_name */
Neil Schemenauerdbf409f2002-03-18 20:43:51 +0000219 sizeof(calliterobject), /* tp_basicsize */
Guido van Rossum05311482001-04-20 21:06:46 +0000220 0, /* tp_itemsize */
221 /* methods */
222 (destructor)calliter_dealloc, /* tp_dealloc */
223 0, /* tp_print */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000224 0, /* tp_getattr */
Guido van Rossum05311482001-04-20 21:06:46 +0000225 0, /* tp_setattr */
226 0, /* tp_compare */
227 0, /* tp_repr */
228 0, /* tp_as_number */
229 0, /* tp_as_sequence */
230 0, /* tp_as_mapping */
231 0, /* tp_hash */
232 0, /* tp_call */
233 0, /* tp_str */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000234 PyObject_GenericGetAttr, /* tp_getattro */
Guido van Rossum05311482001-04-20 21:06:46 +0000235 0, /* tp_setattro */
236 0, /* tp_as_buffer */
Neil Schemenauerdbf409f2002-03-18 20:43:51 +0000237 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
Guido van Rossum05311482001-04-20 21:06:46 +0000238 0, /* tp_doc */
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000239 (traverseproc)calliter_traverse, /* tp_traverse */
Guido van Rossum05311482001-04-20 21:06:46 +0000240 0, /* tp_clear */
241 0, /* tp_richcompare */
242 0, /* tp_weaklistoffset */
243 (getiterfunc)iter_getiter, /* tp_iter */
Guido van Rossum213c7a62001-04-23 14:08:49 +0000244 (iternextfunc)calliter_iternext, /* tp_iternext */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000245 calliter_methods, /* tp_methods */
246 0, /* tp_members */
247 0, /* tp_getset */
248 0, /* tp_base */
249 0, /* tp_dict */
250 0, /* tp_descr_get */
251 0, /* tp_descr_set */
Guido van Rossum05311482001-04-20 21:06:46 +0000252};