blob: bd0544ccd90aae0c2b5e2b9e699255b9264154aa [file] [log] [blame]
Guido van Rossum05311482001-04-20 21:06:46 +00001/* Iterator objects */
2
3#include "Python.h"
4
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +00005/* Convenience function to get builtins.iter or builtins.reversed */
6PyObject *
7_PyIter_GetBuiltin(const char *iter)
8{
9 PyObject *mod, *attr;
10 mod = PyImport_ImportModule("builtins");
11 if (mod == NULL)
12 return NULL;
13 attr = PyObject_GetAttrString(mod, iter);
14 Py_DECREF(mod);
15 return attr;
16}
17
Guido van Rossum05311482001-04-20 21:06:46 +000018typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000019 PyObject_HEAD
20 long it_index;
21 PyObject *it_seq; /* Set to NULL when iterator is exhausted */
Guido van Rossum213c7a62001-04-23 14:08:49 +000022} seqiterobject;
Guido van Rossum05311482001-04-20 21:06:46 +000023
24PyObject *
Guido van Rossum213c7a62001-04-23 14:08:49 +000025PySeqIter_New(PyObject *seq)
Guido van Rossum05311482001-04-20 21:06:46 +000026{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000027 seqiterobject *it;
Martin v. Löwis01f94bd2002-05-08 08:44:21 +000028
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000029 if (!PySequence_Check(seq)) {
30 PyErr_BadInternalCall();
31 return NULL;
32 }
33 it = PyObject_GC_New(seqiterobject, &PySeqIter_Type);
34 if (it == NULL)
35 return NULL;
36 it->it_index = 0;
37 Py_INCREF(seq);
38 it->it_seq = seq;
39 _PyObject_GC_TRACK(it);
40 return (PyObject *)it;
Guido van Rossum05311482001-04-20 21:06:46 +000041}
Guido van Rossum613bed32002-07-16 20:24:46 +000042
Guido van Rossum05311482001-04-20 21:06:46 +000043static void
Guido van Rossum213c7a62001-04-23 14:08:49 +000044iter_dealloc(seqiterobject *it)
Guido van Rossum05311482001-04-20 21:06:46 +000045{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000046 _PyObject_GC_UNTRACK(it);
47 Py_XDECREF(it->it_seq);
48 PyObject_GC_Del(it);
Guido van Rossum05311482001-04-20 21:06:46 +000049}
50
Neil Schemenauer7eac9b72001-07-12 13:27:25 +000051static int
52iter_traverse(seqiterobject *it, visitproc visit, void *arg)
53{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000054 Py_VISIT(it->it_seq);
55 return 0;
Neil Schemenauer7eac9b72001-07-12 13:27:25 +000056}
57
Guido van Rossum05311482001-04-20 21:06:46 +000058static PyObject *
Guido van Rossum213c7a62001-04-23 14:08:49 +000059iter_iternext(PyObject *iterator)
60{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000061 seqiterobject *it;
62 PyObject *seq;
63 PyObject *result;
Guido van Rossum213c7a62001-04-23 14:08:49 +000064
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000065 assert(PySeqIter_Check(iterator));
66 it = (seqiterobject *)iterator;
67 seq = it->it_seq;
68 if (seq == NULL)
69 return NULL;
Guido van Rossum213c7a62001-04-23 14:08:49 +000070
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000071 result = PySequence_GetItem(seq, it->it_index);
72 if (result != NULL) {
73 it->it_index++;
74 return result;
75 }
76 if (PyErr_ExceptionMatches(PyExc_IndexError) ||
77 PyErr_ExceptionMatches(PyExc_StopIteration))
78 {
79 PyErr_Clear();
80 Py_DECREF(seq);
81 it->it_seq = NULL;
82 }
83 return NULL;
Guido van Rossum213c7a62001-04-23 14:08:49 +000084}
85
Raymond Hettinger6b27cda2005-09-24 21:23:05 +000086static PyObject *
Raymond Hettinger435bf582004-03-18 22:43:10 +000087iter_len(seqiterobject *it)
88{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000089 Py_ssize_t seqsize, len;
Raymond Hettinger7892b1c2004-04-12 18:10:01 +000090
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000091 if (it->it_seq) {
92 seqsize = PySequence_Size(it->it_seq);
93 if (seqsize == -1)
94 return NULL;
95 len = seqsize - it->it_index;
96 if (len >= 0)
97 return PyLong_FromSsize_t(len);
98 }
99 return PyLong_FromLong(0);
Raymond Hettinger435bf582004-03-18 22:43:10 +0000100}
101
Armin Rigof5b3e362006-02-11 21:32:43 +0000102PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
Raymond Hettinger6b27cda2005-09-24 21:23:05 +0000103
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000104static PyObject *
105iter_reduce(seqiterobject *it)
106{
107 if (it->it_seq != NULL)
108 return Py_BuildValue("N(O)n", _PyIter_GetBuiltin("iter"),
109 it->it_seq, it->it_index);
110 else
111 return Py_BuildValue("N(())", _PyIter_GetBuiltin("iter"));
112}
113
114PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
115
116static PyObject *
117iter_setstate(seqiterobject *it, PyObject *state)
118{
119 Py_ssize_t index = PyLong_AsSsize_t(state);
120 if (index == -1 && PyErr_Occurred())
121 return NULL;
122 if (it->it_seq != NULL) {
123 if (index < 0)
124 index = 0;
125 it->it_index = index;
126 }
127 Py_RETURN_NONE;
128}
129
130PyDoc_STRVAR(setstate_doc, "Set state information for unpickling.");
131
Raymond Hettinger6b27cda2005-09-24 21:23:05 +0000132static PyMethodDef seqiter_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000133 {"__length_hint__", (PyCFunction)iter_len, METH_NOARGS, length_hint_doc},
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000134 {"__reduce__", (PyCFunction)iter_reduce, METH_NOARGS, reduce_doc},
135 {"__setstate__", (PyCFunction)iter_setstate, METH_O, setstate_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000136 {NULL, NULL} /* sentinel */
Raymond Hettinger435bf582004-03-18 22:43:10 +0000137};
138
Guido van Rossum213c7a62001-04-23 14:08:49 +0000139PyTypeObject PySeqIter_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000140 PyVarObject_HEAD_INIT(&PyType_Type, 0)
141 "iterator", /* tp_name */
142 sizeof(seqiterobject), /* tp_basicsize */
143 0, /* tp_itemsize */
144 /* methods */
145 (destructor)iter_dealloc, /* tp_dealloc */
146 0, /* tp_print */
147 0, /* tp_getattr */
148 0, /* tp_setattr */
149 0, /* tp_reserved */
150 0, /* tp_repr */
151 0, /* tp_as_number */
152 0, /* tp_as_sequence */
153 0, /* tp_as_mapping */
154 0, /* tp_hash */
155 0, /* tp_call */
156 0, /* tp_str */
157 PyObject_GenericGetAttr, /* tp_getattro */
158 0, /* tp_setattro */
159 0, /* tp_as_buffer */
160 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
161 0, /* tp_doc */
162 (traverseproc)iter_traverse, /* tp_traverse */
163 0, /* tp_clear */
164 0, /* tp_richcompare */
165 0, /* tp_weaklistoffset */
166 PyObject_SelfIter, /* tp_iter */
167 iter_iternext, /* tp_iternext */
168 seqiter_methods, /* tp_methods */
169 0, /* tp_members */
Guido van Rossum05311482001-04-20 21:06:46 +0000170};
171
172/* -------------------------------------- */
173
174typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000175 PyObject_HEAD
176 PyObject *it_callable; /* Set to NULL when iterator is exhausted */
177 PyObject *it_sentinel; /* Set to NULL when iterator is exhausted */
Guido van Rossum05311482001-04-20 21:06:46 +0000178} calliterobject;
179
180PyObject *
181PyCallIter_New(PyObject *callable, PyObject *sentinel)
182{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000183 calliterobject *it;
184 it = PyObject_GC_New(calliterobject, &PyCallIter_Type);
185 if (it == NULL)
186 return NULL;
187 Py_INCREF(callable);
188 it->it_callable = callable;
189 Py_INCREF(sentinel);
190 it->it_sentinel = sentinel;
191 _PyObject_GC_TRACK(it);
192 return (PyObject *)it;
Guido van Rossum05311482001-04-20 21:06:46 +0000193}
194static void
195calliter_dealloc(calliterobject *it)
196{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000197 _PyObject_GC_UNTRACK(it);
198 Py_XDECREF(it->it_callable);
199 Py_XDECREF(it->it_sentinel);
200 PyObject_GC_Del(it);
Guido van Rossum05311482001-04-20 21:06:46 +0000201}
Guido van Rossum213c7a62001-04-23 14:08:49 +0000202
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000203static int
204calliter_traverse(calliterobject *it, visitproc visit, void *arg)
205{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000206 Py_VISIT(it->it_callable);
207 Py_VISIT(it->it_sentinel);
208 return 0;
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000209}
210
Guido van Rossum05311482001-04-20 21:06:46 +0000211static PyObject *
Guido van Rossum213c7a62001-04-23 14:08:49 +0000212calliter_iternext(calliterobject *it)
213{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000214 if (it->it_callable != NULL) {
215 PyObject *args = PyTuple_New(0);
216 PyObject *result;
217 if (args == NULL)
218 return NULL;
219 result = PyObject_Call(it->it_callable, args, NULL);
220 Py_DECREF(args);
221 if (result != NULL) {
222 int ok;
Raymond Hettinger1b669962010-08-07 05:54:08 +0000223 ok = PyObject_RichCompareBool(it->it_sentinel, result, Py_EQ);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000224 if (ok == 0)
225 return result; /* Common case, fast path */
226 Py_DECREF(result);
227 if (ok > 0) {
228 Py_CLEAR(it->it_callable);
229 Py_CLEAR(it->it_sentinel);
230 }
231 }
232 else if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
233 PyErr_Clear();
234 Py_CLEAR(it->it_callable);
235 Py_CLEAR(it->it_sentinel);
236 }
237 }
238 return NULL;
Guido van Rossum213c7a62001-04-23 14:08:49 +0000239}
240
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000241static PyObject *
242calliter_reduce(calliterobject *it)
243{
244 if (it->it_callable != NULL && it->it_sentinel != NULL)
245 return Py_BuildValue("N(OO)", _PyIter_GetBuiltin("iter"),
246 it->it_callable, it->it_sentinel);
247 else
248 return Py_BuildValue("N(())", _PyIter_GetBuiltin("iter"));
249}
250
251static PyMethodDef calliter_methods[] = {
252 {"__reduce__", (PyCFunction)calliter_reduce, METH_NOARGS, reduce_doc},
253 {NULL, NULL} /* sentinel */
254};
255
Guido van Rossum05311482001-04-20 21:06:46 +0000256PyTypeObject PyCallIter_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000257 PyVarObject_HEAD_INIT(&PyType_Type, 0)
258 "callable_iterator", /* tp_name */
259 sizeof(calliterobject), /* tp_basicsize */
260 0, /* tp_itemsize */
261 /* methods */
262 (destructor)calliter_dealloc, /* tp_dealloc */
263 0, /* tp_print */
264 0, /* tp_getattr */
265 0, /* tp_setattr */
266 0, /* tp_reserved */
267 0, /* tp_repr */
268 0, /* tp_as_number */
269 0, /* tp_as_sequence */
270 0, /* tp_as_mapping */
271 0, /* tp_hash */
272 0, /* tp_call */
273 0, /* tp_str */
274 PyObject_GenericGetAttr, /* tp_getattro */
275 0, /* tp_setattro */
276 0, /* tp_as_buffer */
277 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
278 0, /* tp_doc */
279 (traverseproc)calliter_traverse, /* tp_traverse */
280 0, /* tp_clear */
281 0, /* tp_richcompare */
282 0, /* tp_weaklistoffset */
283 PyObject_SelfIter, /* tp_iter */
284 (iternextfunc)calliter_iternext, /* tp_iternext */
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000285 calliter_methods, /* tp_methods */
Guido van Rossum05311482001-04-20 21:06:46 +0000286};
Guido van Rossumb65fb332006-08-25 23:26:40 +0000287
288