blob: 51104fbe9695fdfd055e9e93189222da401e66ef [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"
Guido van Rossum05311482001-04-20 21:06:46 +00006
7typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00008 PyObject_HEAD
Victor Stinnere0b99ba2013-06-04 23:02:46 +02009 Py_ssize_t it_index;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000010 PyObject *it_seq; /* Set to NULL when iterator is exhausted */
Guido van Rossum213c7a62001-04-23 14:08:49 +000011} seqiterobject;
Guido van Rossum05311482001-04-20 21:06:46 +000012
Hai Shi46874c22020-01-30 17:20:25 -060013_Py_IDENTIFIER(iter);
14
Guido van Rossum05311482001-04-20 21:06:46 +000015PyObject *
Guido van Rossum213c7a62001-04-23 14:08:49 +000016PySeqIter_New(PyObject *seq)
Guido van Rossum05311482001-04-20 21:06:46 +000017{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000018 seqiterobject *it;
Martin v. Löwis01f94bd2002-05-08 08:44:21 +000019
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000020 if (!PySequence_Check(seq)) {
21 PyErr_BadInternalCall();
22 return NULL;
23 }
24 it = PyObject_GC_New(seqiterobject, &PySeqIter_Type);
25 if (it == NULL)
26 return NULL;
27 it->it_index = 0;
28 Py_INCREF(seq);
29 it->it_seq = seq;
30 _PyObject_GC_TRACK(it);
31 return (PyObject *)it;
Guido van Rossum05311482001-04-20 21:06:46 +000032}
Guido van Rossum613bed32002-07-16 20:24:46 +000033
Guido van Rossum05311482001-04-20 21:06:46 +000034static void
Guido van Rossum213c7a62001-04-23 14:08:49 +000035iter_dealloc(seqiterobject *it)
Guido van Rossum05311482001-04-20 21:06:46 +000036{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000037 _PyObject_GC_UNTRACK(it);
38 Py_XDECREF(it->it_seq);
39 PyObject_GC_Del(it);
Guido van Rossum05311482001-04-20 21:06:46 +000040}
41
Neil Schemenauer7eac9b72001-07-12 13:27:25 +000042static int
43iter_traverse(seqiterobject *it, visitproc visit, void *arg)
44{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000045 Py_VISIT(it->it_seq);
46 return 0;
Neil Schemenauer7eac9b72001-07-12 13:27:25 +000047}
48
Guido van Rossum05311482001-04-20 21:06:46 +000049static PyObject *
Guido van Rossum213c7a62001-04-23 14:08:49 +000050iter_iternext(PyObject *iterator)
51{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000052 seqiterobject *it;
53 PyObject *seq;
54 PyObject *result;
Guido van Rossum213c7a62001-04-23 14:08:49 +000055
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000056 assert(PySeqIter_Check(iterator));
57 it = (seqiterobject *)iterator;
58 seq = it->it_seq;
59 if (seq == NULL)
60 return NULL;
Serhiy Storchaka4faf5c52015-05-21 20:50:25 +030061 if (it->it_index == PY_SSIZE_T_MAX) {
62 PyErr_SetString(PyExc_OverflowError,
63 "iter index too large");
64 return NULL;
65 }
Guido van Rossum213c7a62001-04-23 14:08:49 +000066
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000067 result = PySequence_GetItem(seq, it->it_index);
68 if (result != NULL) {
69 it->it_index++;
70 return result;
71 }
72 if (PyErr_ExceptionMatches(PyExc_IndexError) ||
73 PyErr_ExceptionMatches(PyExc_StopIteration))
74 {
75 PyErr_Clear();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000076 it->it_seq = NULL;
Serhiy Storchakafbb1c5e2016-03-30 20:40:02 +030077 Py_DECREF(seq);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000078 }
79 return NULL;
Guido van Rossum213c7a62001-04-23 14:08:49 +000080}
81
Raymond Hettinger6b27cda2005-09-24 21:23:05 +000082static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +053083iter_len(seqiterobject *it, PyObject *Py_UNUSED(ignored))
Raymond Hettinger435bf582004-03-18 22:43:10 +000084{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000085 Py_ssize_t seqsize, len;
Raymond Hettinger7892b1c2004-04-12 18:10:01 +000086
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000087 if (it->it_seq) {
Armin Ronacheraa9a79d2012-10-06 14:03:24 +020088 if (_PyObject_HasLen(it->it_seq)) {
89 seqsize = PySequence_Size(it->it_seq);
90 if (seqsize == -1)
91 return NULL;
92 }
93 else {
Armin Ronacher23c5bb42012-10-06 14:30:32 +020094 Py_RETURN_NOTIMPLEMENTED;
Armin Ronacheraa9a79d2012-10-06 14:03:24 +020095 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000096 len = seqsize - it->it_index;
97 if (len >= 0)
98 return PyLong_FromSsize_t(len);
99 }
100 return PyLong_FromLong(0);
Raymond Hettinger435bf582004-03-18 22:43:10 +0000101}
102
Armin Rigof5b3e362006-02-11 21:32:43 +0000103PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
Raymond Hettinger6b27cda2005-09-24 21:23:05 +0000104
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000105static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530106iter_reduce(seqiterobject *it, PyObject *Py_UNUSED(ignored))
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000107{
108 if (it->it_seq != NULL)
Serhiy Storchakabb86bf42018-12-11 08:28:18 +0200109 return Py_BuildValue("N(O)n", _PyEval_GetBuiltinId(&PyId_iter),
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000110 it->it_seq, it->it_index);
111 else
Serhiy Storchakabb86bf42018-12-11 08:28:18 +0200112 return Py_BuildValue("N(())", _PyEval_GetBuiltinId(&PyId_iter));
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000113}
114
115PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
116
117static PyObject *
118iter_setstate(seqiterobject *it, PyObject *state)
119{
120 Py_ssize_t index = PyLong_AsSsize_t(state);
121 if (index == -1 && PyErr_Occurred())
122 return NULL;
123 if (it->it_seq != NULL) {
124 if (index < 0)
125 index = 0;
126 it->it_index = index;
127 }
128 Py_RETURN_NONE;
129}
130
131PyDoc_STRVAR(setstate_doc, "Set state information for unpickling.");
132
Raymond Hettinger6b27cda2005-09-24 21:23:05 +0000133static PyMethodDef seqiter_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000134 {"__length_hint__", (PyCFunction)iter_len, METH_NOARGS, length_hint_doc},
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000135 {"__reduce__", (PyCFunction)iter_reduce, METH_NOARGS, reduce_doc},
136 {"__setstate__", (PyCFunction)iter_setstate, METH_O, setstate_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000137 {NULL, NULL} /* sentinel */
Raymond Hettinger435bf582004-03-18 22:43:10 +0000138};
139
Guido van Rossum213c7a62001-04-23 14:08:49 +0000140PyTypeObject PySeqIter_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000141 PyVarObject_HEAD_INIT(&PyType_Type, 0)
142 "iterator", /* tp_name */
143 sizeof(seqiterobject), /* tp_basicsize */
144 0, /* tp_itemsize */
145 /* methods */
146 (destructor)iter_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200147 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000148 0, /* tp_getattr */
149 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200150 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000151 0, /* tp_repr */
152 0, /* tp_as_number */
153 0, /* tp_as_sequence */
154 0, /* tp_as_mapping */
155 0, /* tp_hash */
156 0, /* tp_call */
157 0, /* tp_str */
158 PyObject_GenericGetAttr, /* tp_getattro */
159 0, /* tp_setattro */
160 0, /* tp_as_buffer */
161 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
162 0, /* tp_doc */
163 (traverseproc)iter_traverse, /* tp_traverse */
164 0, /* tp_clear */
165 0, /* tp_richcompare */
166 0, /* tp_weaklistoffset */
167 PyObject_SelfIter, /* tp_iter */
168 iter_iternext, /* tp_iternext */
169 seqiter_methods, /* tp_methods */
170 0, /* tp_members */
Guido van Rossum05311482001-04-20 21:06:46 +0000171};
172
173/* -------------------------------------- */
174
175typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000176 PyObject_HEAD
177 PyObject *it_callable; /* Set to NULL when iterator is exhausted */
178 PyObject *it_sentinel; /* Set to NULL when iterator is exhausted */
Guido van Rossum05311482001-04-20 21:06:46 +0000179} calliterobject;
180
181PyObject *
182PyCallIter_New(PyObject *callable, PyObject *sentinel)
183{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000184 calliterobject *it;
185 it = PyObject_GC_New(calliterobject, &PyCallIter_Type);
186 if (it == NULL)
187 return NULL;
188 Py_INCREF(callable);
189 it->it_callable = callable;
190 Py_INCREF(sentinel);
191 it->it_sentinel = sentinel;
192 _PyObject_GC_TRACK(it);
193 return (PyObject *)it;
Guido van Rossum05311482001-04-20 21:06:46 +0000194}
195static void
196calliter_dealloc(calliterobject *it)
197{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000198 _PyObject_GC_UNTRACK(it);
199 Py_XDECREF(it->it_callable);
200 Py_XDECREF(it->it_sentinel);
201 PyObject_GC_Del(it);
Guido van Rossum05311482001-04-20 21:06:46 +0000202}
Guido van Rossum213c7a62001-04-23 14:08:49 +0000203
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000204static int
205calliter_traverse(calliterobject *it, visitproc visit, void *arg)
206{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000207 Py_VISIT(it->it_callable);
208 Py_VISIT(it->it_sentinel);
209 return 0;
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000210}
211
Guido van Rossum05311482001-04-20 21:06:46 +0000212static PyObject *
Guido van Rossum213c7a62001-04-23 14:08:49 +0000213calliter_iternext(calliterobject *it)
214{
Victor Stinner99ee9c72016-08-19 18:47:10 +0200215 PyObject *result;
216
217 if (it->it_callable == NULL) {
218 return NULL;
219 }
220
Victor Stinner559bb6a2016-08-22 22:48:54 +0200221 result = _PyObject_CallNoArg(it->it_callable);
Victor Stinner99ee9c72016-08-19 18:47:10 +0200222 if (result != NULL) {
223 int ok;
224
225 ok = PyObject_RichCompareBool(it->it_sentinel, result, Py_EQ);
226 if (ok == 0) {
227 return result; /* Common case, fast path */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000228 }
Victor Stinner99ee9c72016-08-19 18:47:10 +0200229
230 Py_DECREF(result);
231 if (ok > 0) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000232 Py_CLEAR(it->it_callable);
233 Py_CLEAR(it->it_sentinel);
234 }
235 }
Victor Stinner99ee9c72016-08-19 18:47:10 +0200236 else if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
237 PyErr_Clear();
238 Py_CLEAR(it->it_callable);
239 Py_CLEAR(it->it_sentinel);
240 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000241 return NULL;
Guido van Rossum213c7a62001-04-23 14:08:49 +0000242}
243
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000244static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530245calliter_reduce(calliterobject *it, PyObject *Py_UNUSED(ignored))
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000246{
247 if (it->it_callable != NULL && it->it_sentinel != NULL)
Serhiy Storchakabb86bf42018-12-11 08:28:18 +0200248 return Py_BuildValue("N(OO)", _PyEval_GetBuiltinId(&PyId_iter),
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000249 it->it_callable, it->it_sentinel);
250 else
Serhiy Storchakabb86bf42018-12-11 08:28:18 +0200251 return Py_BuildValue("N(())", _PyEval_GetBuiltinId(&PyId_iter));
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000252}
253
254static PyMethodDef calliter_methods[] = {
255 {"__reduce__", (PyCFunction)calliter_reduce, METH_NOARGS, reduce_doc},
256 {NULL, NULL} /* sentinel */
257};
258
Guido van Rossum05311482001-04-20 21:06:46 +0000259PyTypeObject PyCallIter_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000260 PyVarObject_HEAD_INIT(&PyType_Type, 0)
261 "callable_iterator", /* tp_name */
262 sizeof(calliterobject), /* tp_basicsize */
263 0, /* tp_itemsize */
264 /* methods */
265 (destructor)calliter_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200266 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000267 0, /* tp_getattr */
268 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200269 0, /* tp_as_async */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000270 0, /* tp_repr */
271 0, /* tp_as_number */
272 0, /* tp_as_sequence */
273 0, /* tp_as_mapping */
274 0, /* tp_hash */
275 0, /* tp_call */
276 0, /* tp_str */
277 PyObject_GenericGetAttr, /* tp_getattro */
278 0, /* tp_setattro */
279 0, /* tp_as_buffer */
280 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
281 0, /* tp_doc */
282 (traverseproc)calliter_traverse, /* tp_traverse */
283 0, /* tp_clear */
284 0, /* tp_richcompare */
285 0, /* tp_weaklistoffset */
286 PyObject_SelfIter, /* tp_iter */
287 (iternextfunc)calliter_iternext, /* tp_iternext */
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000288 calliter_methods, /* tp_methods */
Guido van Rossum05311482001-04-20 21:06:46 +0000289};
Guido van Rossumb65fb332006-08-25 23:26:40 +0000290
291