blob: fe1de7e211c5d6b1b702677b4a9365b23ad8227f [file] [log] [blame]
Guido van Rossum05311482001-04-20 21:06:46 +00001/* Iterator objects */
2
3#include "Python.h"
Victor Stinnerbcda8f12018-11-21 22:27:47 +01004#include "pycore_object.h"
Victor Stinner621cebe2018-11-12 16:53:38 +01005#include "pycore_pymem.h"
6#include "pycore_pystate.h"
Guido van Rossum05311482001-04-20 21:06:46 +00007
8typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00009 PyObject_HEAD
Victor Stinnere0b99ba2013-06-04 23:02:46 +020010 Py_ssize_t it_index;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000011 PyObject *it_seq; /* Set to NULL when iterator is exhausted */
Guido van Rossum213c7a62001-04-23 14:08:49 +000012} seqiterobject;
Guido van Rossum05311482001-04-20 21:06:46 +000013
Hai Shi46874c22020-01-30 17:20:25 -060014_Py_IDENTIFIER(iter);
15
Guido van Rossum05311482001-04-20 21:06:46 +000016PyObject *
Guido van Rossum213c7a62001-04-23 14:08:49 +000017PySeqIter_New(PyObject *seq)
Guido van Rossum05311482001-04-20 21:06:46 +000018{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000019 seqiterobject *it;
Martin v. Löwis01f94bd2002-05-08 08:44:21 +000020
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000021 if (!PySequence_Check(seq)) {
22 PyErr_BadInternalCall();
23 return NULL;
24 }
25 it = PyObject_GC_New(seqiterobject, &PySeqIter_Type);
26 if (it == NULL)
27 return NULL;
28 it->it_index = 0;
29 Py_INCREF(seq);
30 it->it_seq = seq;
31 _PyObject_GC_TRACK(it);
32 return (PyObject *)it;
Guido van Rossum05311482001-04-20 21:06:46 +000033}
Guido van Rossum613bed32002-07-16 20:24:46 +000034
Guido van Rossum05311482001-04-20 21:06:46 +000035static void
Guido van Rossum213c7a62001-04-23 14:08:49 +000036iter_dealloc(seqiterobject *it)
Guido van Rossum05311482001-04-20 21:06:46 +000037{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000038 _PyObject_GC_UNTRACK(it);
39 Py_XDECREF(it->it_seq);
40 PyObject_GC_Del(it);
Guido van Rossum05311482001-04-20 21:06:46 +000041}
42
Neil Schemenauer7eac9b72001-07-12 13:27:25 +000043static int
44iter_traverse(seqiterobject *it, visitproc visit, void *arg)
45{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000046 Py_VISIT(it->it_seq);
47 return 0;
Neil Schemenauer7eac9b72001-07-12 13:27:25 +000048}
49
Guido van Rossum05311482001-04-20 21:06:46 +000050static PyObject *
Guido van Rossum213c7a62001-04-23 14:08:49 +000051iter_iternext(PyObject *iterator)
52{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000053 seqiterobject *it;
54 PyObject *seq;
55 PyObject *result;
Guido van Rossum213c7a62001-04-23 14:08:49 +000056
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000057 assert(PySeqIter_Check(iterator));
58 it = (seqiterobject *)iterator;
59 seq = it->it_seq;
60 if (seq == NULL)
61 return NULL;
Serhiy Storchaka4faf5c52015-05-21 20:50:25 +030062 if (it->it_index == PY_SSIZE_T_MAX) {
63 PyErr_SetString(PyExc_OverflowError,
64 "iter index too large");
65 return NULL;
66 }
Guido van Rossum213c7a62001-04-23 14:08:49 +000067
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000068 result = PySequence_GetItem(seq, it->it_index);
69 if (result != NULL) {
70 it->it_index++;
71 return result;
72 }
73 if (PyErr_ExceptionMatches(PyExc_IndexError) ||
74 PyErr_ExceptionMatches(PyExc_StopIteration))
75 {
76 PyErr_Clear();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000077 it->it_seq = NULL;
Serhiy Storchakafbb1c5e2016-03-30 20:40:02 +030078 Py_DECREF(seq);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000079 }
80 return NULL;
Guido van Rossum213c7a62001-04-23 14:08:49 +000081}
82
Raymond Hettinger6b27cda2005-09-24 21:23:05 +000083static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +053084iter_len(seqiterobject *it, PyObject *Py_UNUSED(ignored))
Raymond Hettinger435bf582004-03-18 22:43:10 +000085{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000086 Py_ssize_t seqsize, len;
Raymond Hettinger7892b1c2004-04-12 18:10:01 +000087
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000088 if (it->it_seq) {
Armin Ronacheraa9a79d2012-10-06 14:03:24 +020089 if (_PyObject_HasLen(it->it_seq)) {
90 seqsize = PySequence_Size(it->it_seq);
91 if (seqsize == -1)
92 return NULL;
93 }
94 else {
Armin Ronacher23c5bb42012-10-06 14:30:32 +020095 Py_RETURN_NOTIMPLEMENTED;
Armin Ronacheraa9a79d2012-10-06 14:03:24 +020096 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000097 len = seqsize - it->it_index;
98 if (len >= 0)
99 return PyLong_FromSsize_t(len);
100 }
101 return PyLong_FromLong(0);
Raymond Hettinger435bf582004-03-18 22:43:10 +0000102}
103
Armin Rigof5b3e362006-02-11 21:32:43 +0000104PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
Raymond Hettinger6b27cda2005-09-24 21:23:05 +0000105
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000106static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530107iter_reduce(seqiterobject *it, PyObject *Py_UNUSED(ignored))
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000108{
109 if (it->it_seq != NULL)
Serhiy Storchakabb86bf42018-12-11 08:28:18 +0200110 return Py_BuildValue("N(O)n", _PyEval_GetBuiltinId(&PyId_iter),
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000111 it->it_seq, it->it_index);
112 else
Serhiy Storchakabb86bf42018-12-11 08:28:18 +0200113 return Py_BuildValue("N(())", _PyEval_GetBuiltinId(&PyId_iter));
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000114}
115
116PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
117
118static PyObject *
119iter_setstate(seqiterobject *it, PyObject *state)
120{
121 Py_ssize_t index = PyLong_AsSsize_t(state);
122 if (index == -1 && PyErr_Occurred())
123 return NULL;
124 if (it->it_seq != NULL) {
125 if (index < 0)
126 index = 0;
127 it->it_index = index;
128 }
129 Py_RETURN_NONE;
130}
131
132PyDoc_STRVAR(setstate_doc, "Set state information for unpickling.");
133
Raymond Hettinger6b27cda2005-09-24 21:23:05 +0000134static PyMethodDef seqiter_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000135 {"__length_hint__", (PyCFunction)iter_len, METH_NOARGS, length_hint_doc},
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000136 {"__reduce__", (PyCFunction)iter_reduce, METH_NOARGS, reduce_doc},
137 {"__setstate__", (PyCFunction)iter_setstate, METH_O, setstate_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000138 {NULL, NULL} /* sentinel */
Raymond Hettinger435bf582004-03-18 22:43:10 +0000139};
140
Guido van Rossum213c7a62001-04-23 14:08:49 +0000141PyTypeObject PySeqIter_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000142 PyVarObject_HEAD_INIT(&PyType_Type, 0)
143 "iterator", /* tp_name */
144 sizeof(seqiterobject), /* tp_basicsize */
145 0, /* tp_itemsize */
146 /* methods */
147 (destructor)iter_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200148 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000149 0, /* tp_getattr */
150 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200151 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000152 0, /* tp_repr */
153 0, /* tp_as_number */
154 0, /* tp_as_sequence */
155 0, /* tp_as_mapping */
156 0, /* tp_hash */
157 0, /* tp_call */
158 0, /* tp_str */
159 PyObject_GenericGetAttr, /* tp_getattro */
160 0, /* tp_setattro */
161 0, /* tp_as_buffer */
162 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
163 0, /* tp_doc */
164 (traverseproc)iter_traverse, /* tp_traverse */
165 0, /* tp_clear */
166 0, /* tp_richcompare */
167 0, /* tp_weaklistoffset */
168 PyObject_SelfIter, /* tp_iter */
169 iter_iternext, /* tp_iternext */
170 seqiter_methods, /* tp_methods */
171 0, /* tp_members */
Guido van Rossum05311482001-04-20 21:06:46 +0000172};
173
174/* -------------------------------------- */
175
176typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000177 PyObject_HEAD
178 PyObject *it_callable; /* Set to NULL when iterator is exhausted */
179 PyObject *it_sentinel; /* Set to NULL when iterator is exhausted */
Guido van Rossum05311482001-04-20 21:06:46 +0000180} calliterobject;
181
182PyObject *
183PyCallIter_New(PyObject *callable, PyObject *sentinel)
184{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000185 calliterobject *it;
186 it = PyObject_GC_New(calliterobject, &PyCallIter_Type);
187 if (it == NULL)
188 return NULL;
189 Py_INCREF(callable);
190 it->it_callable = callable;
191 Py_INCREF(sentinel);
192 it->it_sentinel = sentinel;
193 _PyObject_GC_TRACK(it);
194 return (PyObject *)it;
Guido van Rossum05311482001-04-20 21:06:46 +0000195}
196static void
197calliter_dealloc(calliterobject *it)
198{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000199 _PyObject_GC_UNTRACK(it);
200 Py_XDECREF(it->it_callable);
201 Py_XDECREF(it->it_sentinel);
202 PyObject_GC_Del(it);
Guido van Rossum05311482001-04-20 21:06:46 +0000203}
Guido van Rossum213c7a62001-04-23 14:08:49 +0000204
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000205static int
206calliter_traverse(calliterobject *it, visitproc visit, void *arg)
207{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000208 Py_VISIT(it->it_callable);
209 Py_VISIT(it->it_sentinel);
210 return 0;
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000211}
212
Guido van Rossum05311482001-04-20 21:06:46 +0000213static PyObject *
Guido van Rossum213c7a62001-04-23 14:08:49 +0000214calliter_iternext(calliterobject *it)
215{
Victor Stinner99ee9c72016-08-19 18:47:10 +0200216 PyObject *result;
217
218 if (it->it_callable == NULL) {
219 return NULL;
220 }
221
Victor Stinner559bb6a2016-08-22 22:48:54 +0200222 result = _PyObject_CallNoArg(it->it_callable);
Victor Stinner99ee9c72016-08-19 18:47:10 +0200223 if (result != NULL) {
224 int ok;
225
226 ok = PyObject_RichCompareBool(it->it_sentinel, result, Py_EQ);
227 if (ok == 0) {
228 return result; /* Common case, fast path */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000229 }
Victor Stinner99ee9c72016-08-19 18:47:10 +0200230
231 Py_DECREF(result);
232 if (ok > 0) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000233 Py_CLEAR(it->it_callable);
234 Py_CLEAR(it->it_sentinel);
235 }
236 }
Victor Stinner99ee9c72016-08-19 18:47:10 +0200237 else if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
238 PyErr_Clear();
239 Py_CLEAR(it->it_callable);
240 Py_CLEAR(it->it_sentinel);
241 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000242 return NULL;
Guido van Rossum213c7a62001-04-23 14:08:49 +0000243}
244
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000245static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530246calliter_reduce(calliterobject *it, PyObject *Py_UNUSED(ignored))
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000247{
248 if (it->it_callable != NULL && it->it_sentinel != NULL)
Serhiy Storchakabb86bf42018-12-11 08:28:18 +0200249 return Py_BuildValue("N(OO)", _PyEval_GetBuiltinId(&PyId_iter),
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000250 it->it_callable, it->it_sentinel);
251 else
Serhiy Storchakabb86bf42018-12-11 08:28:18 +0200252 return Py_BuildValue("N(())", _PyEval_GetBuiltinId(&PyId_iter));
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000253}
254
255static PyMethodDef calliter_methods[] = {
256 {"__reduce__", (PyCFunction)calliter_reduce, METH_NOARGS, reduce_doc},
257 {NULL, NULL} /* sentinel */
258};
259
Guido van Rossum05311482001-04-20 21:06:46 +0000260PyTypeObject PyCallIter_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000261 PyVarObject_HEAD_INIT(&PyType_Type, 0)
262 "callable_iterator", /* tp_name */
263 sizeof(calliterobject), /* tp_basicsize */
264 0, /* tp_itemsize */
265 /* methods */
266 (destructor)calliter_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200267 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000268 0, /* tp_getattr */
269 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200270 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000271 0, /* tp_repr */
272 0, /* tp_as_number */
273 0, /* tp_as_sequence */
274 0, /* tp_as_mapping */
275 0, /* tp_hash */
276 0, /* tp_call */
277 0, /* tp_str */
278 PyObject_GenericGetAttr, /* tp_getattro */
279 0, /* tp_setattro */
280 0, /* tp_as_buffer */
281 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
282 0, /* tp_doc */
283 (traverseproc)calliter_traverse, /* tp_traverse */
284 0, /* tp_clear */
285 0, /* tp_richcompare */
286 0, /* tp_weaklistoffset */
287 PyObject_SelfIter, /* tp_iter */
288 (iternextfunc)calliter_iternext, /* tp_iternext */
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000289 calliter_methods, /* tp_methods */
Guido van Rossum05311482001-04-20 21:06:46 +0000290};
Guido van Rossumb65fb332006-08-25 23:26:40 +0000291
292