blob: 8601980e87c940b6b57a7eb178524f4cd3812ae0 [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 +000048/* Return (value, 0) if OK; (NULL, 0) at end; (NULL, -1) if exception */
49static PyObject *
50iter_iternext(PyObject *iterator)
51{
52 seqiterobject *it;
53 PyObject *seq;
54
55 assert(PySeqIter_Check(iterator));
56 it = (seqiterobject *)iterator;
57 seq = it->it_seq;
58
59 if (PyList_Check(seq)) {
60 PyObject *item;
61 if (it->it_index >= PyList_GET_SIZE(seq)) {
62 return NULL;
63 }
64 item = PyList_GET_ITEM(seq, it->it_index);
65 it->it_index++;
66 Py_INCREF(item);
67 return item;
68 }
69 else {
70 PyObject *result = PySequence_GetItem(seq, it->it_index++);
71 if (result != NULL) {
72 return result;
73 }
74 if (PyErr_ExceptionMatches(PyExc_IndexError) ||
75 PyErr_ExceptionMatches(PyExc_StopIteration)) {
76 PyErr_Clear();
77 return NULL;
78 }
79 else {
80 return NULL;
81 }
82 }
83}
84
Guido van Rossum05311482001-04-20 21:06:46 +000085static PyMethodDef iter_methods[] = {
86 {"next", (PyCFunction)iter_next, METH_VARARGS,
87 "it.next() -- get the next value, or raise StopIteration"},
88 {NULL, NULL} /* sentinel */
89};
90
91static PyObject *
Guido van Rossum213c7a62001-04-23 14:08:49 +000092iter_getattr(seqiterobject *it, char *name)
Guido van Rossum05311482001-04-20 21:06:46 +000093{
94 return Py_FindMethod(iter_methods, (PyObject *)it, name);
95}
96
Guido van Rossum213c7a62001-04-23 14:08:49 +000097PyTypeObject PySeqIter_Type = {
Guido van Rossum05311482001-04-20 21:06:46 +000098 PyObject_HEAD_INIT(&PyType_Type)
99 0, /* ob_size */
100 "iterator", /* tp_name */
Guido van Rossum213c7a62001-04-23 14:08:49 +0000101 sizeof(seqiterobject), /* tp_basicsize */
Guido van Rossum05311482001-04-20 21:06:46 +0000102 0, /* tp_itemsize */
103 /* methods */
104 (destructor)iter_dealloc, /* tp_dealloc */
105 0, /* tp_print */
106 (getattrfunc)iter_getattr, /* tp_getattr */
107 0, /* tp_setattr */
108 0, /* tp_compare */
109 0, /* tp_repr */
110 0, /* tp_as_number */
111 0, /* tp_as_sequence */
112 0, /* tp_as_mapping */
113 0, /* tp_hash */
114 0, /* tp_call */
115 0, /* tp_str */
116 0, /* tp_getattro */
117 0, /* tp_setattro */
118 0, /* tp_as_buffer */
119 Py_TPFLAGS_DEFAULT, /* tp_flags */
120 0, /* tp_doc */
121 0, /* tp_traverse */
122 0, /* tp_clear */
123 0, /* tp_richcompare */
124 0, /* tp_weaklistoffset */
125 (getiterfunc)iter_getiter, /* tp_iter */
Guido van Rossum213c7a62001-04-23 14:08:49 +0000126 (iternextfunc)iter_iternext, /* tp_iternext */
Guido van Rossum05311482001-04-20 21:06:46 +0000127};
128
129/* -------------------------------------- */
130
131typedef struct {
132 PyObject_HEAD
133 PyObject *it_callable;
134 PyObject *it_sentinel;
135} calliterobject;
136
137PyObject *
138PyCallIter_New(PyObject *callable, PyObject *sentinel)
139{
140 calliterobject *it;
141 it = PyObject_NEW(calliterobject, &PyCallIter_Type);
142 if (it == NULL)
143 return NULL;
144 Py_INCREF(callable);
145 it->it_callable = callable;
146 Py_INCREF(sentinel);
147 it->it_sentinel = sentinel;
148 return (PyObject *)it;
149}
150static void
151calliter_dealloc(calliterobject *it)
152{
153 Py_DECREF(it->it_callable);
154 Py_DECREF(it->it_sentinel);
155 PyObject_DEL(it);
156}
Guido van Rossum213c7a62001-04-23 14:08:49 +0000157
Guido van Rossum05311482001-04-20 21:06:46 +0000158static PyObject *
159calliter_next(calliterobject *it, PyObject *args)
160{
161 PyObject *result = PyObject_CallObject(it->it_callable, NULL);
162 if (result != NULL) {
163 if (PyObject_RichCompareBool(result, it->it_sentinel, Py_EQ)) {
164 PyErr_SetObject(PyExc_StopIteration, Py_None);
165 Py_DECREF(result);
166 result = NULL;
167 }
168 }
169 return result;
170}
171
172static PyMethodDef calliter_methods[] = {
173 {"next", (PyCFunction)calliter_next, METH_VARARGS,
174 "it.next() -- get the next value, or raise StopIteration"},
175 {NULL, NULL} /* sentinel */
176};
177
178static PyObject *
179calliter_getattr(calliterobject *it, char *name)
180{
181 return Py_FindMethod(calliter_methods, (PyObject *)it, name);
182}
183
Guido van Rossum213c7a62001-04-23 14:08:49 +0000184static PyObject *
185calliter_iternext(calliterobject *it)
186{
187 PyObject *result = PyObject_CallObject(it->it_callable, NULL);
188 if (result != NULL) {
189 if (PyObject_RichCompareBool(result, it->it_sentinel, Py_EQ)) {
190 Py_DECREF(result);
191 result = NULL;
192 }
193 }
194 else if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
195 PyErr_Clear();
196 }
197 return result;
198}
199
Guido van Rossum05311482001-04-20 21:06:46 +0000200PyTypeObject PyCallIter_Type = {
201 PyObject_HEAD_INIT(&PyType_Type)
202 0, /* ob_size */
203 "callable-iterator", /* tp_name */
204 sizeof(calliterobject), /* tp_basicsize */
205 0, /* tp_itemsize */
206 /* methods */
207 (destructor)calliter_dealloc, /* tp_dealloc */
208 0, /* tp_print */
209 (getattrfunc)calliter_getattr, /* tp_getattr */
210 0, /* tp_setattr */
211 0, /* tp_compare */
212 0, /* tp_repr */
213 0, /* tp_as_number */
214 0, /* tp_as_sequence */
215 0, /* tp_as_mapping */
216 0, /* tp_hash */
217 0, /* tp_call */
218 0, /* tp_str */
219 0, /* tp_getattro */
220 0, /* tp_setattro */
221 0, /* tp_as_buffer */
222 Py_TPFLAGS_DEFAULT, /* tp_flags */
223 0, /* tp_doc */
224 0, /* tp_traverse */
225 0, /* tp_clear */
226 0, /* tp_richcompare */
227 0, /* tp_weaklistoffset */
228 (getiterfunc)iter_getiter, /* tp_iter */
Guido van Rossum213c7a62001-04-23 14:08:49 +0000229 (iternextfunc)calliter_iternext, /* tp_iternext */
Guido van Rossum05311482001-04-20 21:06:46 +0000230};