blob: 5783d2085bc07d038d6e28f1b685a275a3e9d330 [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 *
Martin v. Löwise3eb1f22001-08-16 13:15:00 +000040iter_next(seqiterobject *it)
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[] = {
Martin v. Löwise3eb1f22001-08-16 13:15:00 +000094 {"next", (PyCFunction)iter_next, METH_NOARGS,
Guido van Rossum05311482001-04-20 21:06:46 +000095 "it.next() -- get the next value, or raise StopIteration"},
96 {NULL, NULL} /* sentinel */
97};
98
Guido van Rossum213c7a62001-04-23 14:08:49 +000099PyTypeObject PySeqIter_Type = {
Guido van Rossum05311482001-04-20 21:06:46 +0000100 PyObject_HEAD_INIT(&PyType_Type)
101 0, /* ob_size */
102 "iterator", /* tp_name */
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000103 sizeof(seqiterobject) + PyGC_HEAD_SIZE, /* tp_basicsize */
Guido van Rossum05311482001-04-20 21:06:46 +0000104 0, /* tp_itemsize */
105 /* methods */
106 (destructor)iter_dealloc, /* tp_dealloc */
107 0, /* tp_print */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000108 0, /* tp_getattr */
Guido van Rossum05311482001-04-20 21:06:46 +0000109 0, /* tp_setattr */
110 0, /* tp_compare */
111 0, /* tp_repr */
112 0, /* tp_as_number */
113 0, /* tp_as_sequence */
114 0, /* tp_as_mapping */
115 0, /* tp_hash */
116 0, /* tp_call */
117 0, /* tp_str */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000118 PyObject_GenericGetAttr, /* tp_getattro */
Guido van Rossum05311482001-04-20 21:06:46 +0000119 0, /* tp_setattro */
120 0, /* tp_as_buffer */
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000121 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */
Guido van Rossum05311482001-04-20 21:06:46 +0000122 0, /* tp_doc */
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000123 (traverseproc)iter_traverse, /* tp_traverse */
Guido van Rossum05311482001-04-20 21:06:46 +0000124 0, /* tp_clear */
125 0, /* tp_richcompare */
126 0, /* tp_weaklistoffset */
127 (getiterfunc)iter_getiter, /* tp_iter */
Guido van Rossum213c7a62001-04-23 14:08:49 +0000128 (iternextfunc)iter_iternext, /* tp_iternext */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000129 iter_methods, /* tp_methods */
130 0, /* tp_members */
131 0, /* tp_getset */
132 0, /* tp_base */
133 0, /* tp_dict */
134 0, /* tp_descr_get */
135 0, /* tp_descr_set */
Guido van Rossum05311482001-04-20 21:06:46 +0000136};
137
138/* -------------------------------------- */
139
140typedef struct {
141 PyObject_HEAD
142 PyObject *it_callable;
143 PyObject *it_sentinel;
144} calliterobject;
145
146PyObject *
147PyCallIter_New(PyObject *callable, PyObject *sentinel)
148{
149 calliterobject *it;
150 it = PyObject_NEW(calliterobject, &PyCallIter_Type);
151 if (it == NULL)
152 return NULL;
153 Py_INCREF(callable);
154 it->it_callable = callable;
155 Py_INCREF(sentinel);
156 it->it_sentinel = sentinel;
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000157 PyObject_GC_Init(it);
Guido van Rossum05311482001-04-20 21:06:46 +0000158 return (PyObject *)it;
159}
160static void
161calliter_dealloc(calliterobject *it)
162{
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000163 PyObject_GC_Fini(it);
Guido van Rossum05311482001-04-20 21:06:46 +0000164 Py_DECREF(it->it_callable);
165 Py_DECREF(it->it_sentinel);
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000166 it = (calliterobject *) PyObject_AS_GC(it);
Guido van Rossum05311482001-04-20 21:06:46 +0000167 PyObject_DEL(it);
168}
Guido van Rossum213c7a62001-04-23 14:08:49 +0000169
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000170static int
171calliter_traverse(calliterobject *it, visitproc visit, void *arg)
172{
173 int err;
174 if ((err = visit(it->it_callable, arg)))
175 return err;
176 if ((err = visit(it->it_sentinel, arg)))
177 return err;
178 return 0;
179}
180
Guido van Rossum05311482001-04-20 21:06:46 +0000181static PyObject *
182calliter_next(calliterobject *it, PyObject *args)
183{
184 PyObject *result = PyObject_CallObject(it->it_callable, NULL);
185 if (result != NULL) {
186 if (PyObject_RichCompareBool(result, it->it_sentinel, Py_EQ)) {
187 PyErr_SetObject(PyExc_StopIteration, Py_None);
188 Py_DECREF(result);
189 result = NULL;
190 }
191 }
192 return result;
193}
194
195static PyMethodDef calliter_methods[] = {
196 {"next", (PyCFunction)calliter_next, METH_VARARGS,
197 "it.next() -- get the next value, or raise StopIteration"},
198 {NULL, NULL} /* sentinel */
199};
200
201static PyObject *
Guido van Rossum213c7a62001-04-23 14:08:49 +0000202calliter_iternext(calliterobject *it)
203{
204 PyObject *result = PyObject_CallObject(it->it_callable, NULL);
205 if (result != NULL) {
206 if (PyObject_RichCompareBool(result, it->it_sentinel, Py_EQ)) {
207 Py_DECREF(result);
208 result = NULL;
209 }
210 }
211 else if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
212 PyErr_Clear();
213 }
214 return result;
215}
216
Guido van Rossum05311482001-04-20 21:06:46 +0000217PyTypeObject PyCallIter_Type = {
218 PyObject_HEAD_INIT(&PyType_Type)
219 0, /* ob_size */
220 "callable-iterator", /* tp_name */
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000221 sizeof(calliterobject) + PyGC_HEAD_SIZE,/* tp_basicsize */
Guido van Rossum05311482001-04-20 21:06:46 +0000222 0, /* tp_itemsize */
223 /* methods */
224 (destructor)calliter_dealloc, /* tp_dealloc */
225 0, /* tp_print */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000226 0, /* tp_getattr */
Guido van Rossum05311482001-04-20 21:06:46 +0000227 0, /* tp_setattr */
228 0, /* tp_compare */
229 0, /* tp_repr */
230 0, /* tp_as_number */
231 0, /* tp_as_sequence */
232 0, /* tp_as_mapping */
233 0, /* tp_hash */
234 0, /* tp_call */
235 0, /* tp_str */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000236 PyObject_GenericGetAttr, /* tp_getattro */
Guido van Rossum05311482001-04-20 21:06:46 +0000237 0, /* tp_setattro */
238 0, /* tp_as_buffer */
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000239 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */
Guido van Rossum05311482001-04-20 21:06:46 +0000240 0, /* tp_doc */
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000241 (traverseproc)calliter_traverse, /* tp_traverse */
Guido van Rossum05311482001-04-20 21:06:46 +0000242 0, /* tp_clear */
243 0, /* tp_richcompare */
244 0, /* tp_weaklistoffset */
245 (getiterfunc)iter_getiter, /* tp_iter */
Guido van Rossum213c7a62001-04-23 14:08:49 +0000246 (iternextfunc)calliter_iternext, /* tp_iternext */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000247 calliter_methods, /* tp_methods */
248 0, /* tp_members */
249 0, /* tp_getset */
250 0, /* tp_base */
251 0, /* tp_dict */
252 0, /* tp_descr_get */
253 0, /* tp_descr_set */
Guido van Rossum05311482001-04-20 21:06:46 +0000254};