/src/Python-3.8.3/Objects/iterobject.c
Line  | Count  | Source  | 
1  |  | /* Iterator objects */  | 
2  |  |  | 
3  |  | #include "Python.h"  | 
4  |  | #include "pycore_object.h"  | 
5  |  | #include "pycore_pymem.h"  | 
6  |  | #include "pycore_pystate.h"  | 
7  |  |  | 
8  |  | typedef struct { | 
9  |  |     PyObject_HEAD  | 
10  |  |     Py_ssize_t it_index;  | 
11  |  |     PyObject *it_seq; /* Set to NULL when iterator is exhausted */  | 
12  |  | } seqiterobject;  | 
13  |  |  | 
14  |  | PyObject *  | 
15  |  | PySeqIter_New(PyObject *seq)  | 
16  | 67  | { | 
17  | 67  |     seqiterobject *it;  | 
18  |  |  | 
19  | 67  |     if (!PySequence_Check(seq)) { | 
20  | 0  |         PyErr_BadInternalCall();  | 
21  | 0  |         return NULL;  | 
22  | 0  |     }  | 
23  | 67  |     it = PyObject_GC_New(seqiterobject, &PySeqIter_Type);  | 
24  | 67  |     if (it == NULL)  | 
25  | 0  |         return NULL;  | 
26  | 67  |     it->it_index = 0;  | 
27  | 67  |     Py_INCREF(seq);  | 
28  | 67  |     it->it_seq = seq;  | 
29  | 67  |     _PyObject_GC_TRACK(it);  | 
30  | 67  |     return (PyObject *)it;  | 
31  | 67  | }  | 
32  |  |  | 
33  |  | static void  | 
34  |  | iter_dealloc(seqiterobject *it)  | 
35  | 67  | { | 
36  | 67  |     _PyObject_GC_UNTRACK(it);  | 
37  | 67  |     Py_XDECREF(it->it_seq);  | 
38  | 67  |     PyObject_GC_Del(it);  | 
39  | 67  | }  | 
40  |  |  | 
41  |  | static int  | 
42  |  | iter_traverse(seqiterobject *it, visitproc visit, void *arg)  | 
43  | 0  | { | 
44  | 0  |     Py_VISIT(it->it_seq);  | 
45  | 0  |     return 0;  | 
46  | 0  | }  | 
47  |  |  | 
48  |  | static PyObject *  | 
49  |  | iter_iternext(PyObject *iterator)  | 
50  | 147  | { | 
51  | 147  |     seqiterobject *it;  | 
52  | 147  |     PyObject *seq;  | 
53  | 147  |     PyObject *result;  | 
54  |  |  | 
55  | 147  |     assert(PySeqIter_Check(iterator));  | 
56  | 147  |     it = (seqiterobject *)iterator;  | 
57  | 147  |     seq = it->it_seq;  | 
58  | 147  |     if (seq == NULL)  | 
59  | 0  |         return NULL;  | 
60  | 147  |     if (it->it_index == PY_SSIZE_T_MAX) { | 
61  | 0  |         PyErr_SetString(PyExc_OverflowError,  | 
62  | 0  |                         "iter index too large");  | 
63  | 0  |         return NULL;  | 
64  | 0  |     }  | 
65  |  |  | 
66  | 147  |     result = PySequence_GetItem(seq, it->it_index);  | 
67  | 147  |     if (result != NULL) { | 
68  | 80  |         it->it_index++;  | 
69  | 80  |         return result;  | 
70  | 80  |     }  | 
71  | 67  |     if (PyErr_ExceptionMatches(PyExc_IndexError) ||  | 
72  | 0  |         PyErr_ExceptionMatches(PyExc_StopIteration))  | 
73  | 67  |     { | 
74  | 67  |         PyErr_Clear();  | 
75  | 67  |         it->it_seq = NULL;  | 
76  | 67  |         Py_DECREF(seq);  | 
77  | 67  |     }  | 
78  | 67  |     return NULL;  | 
79  | 147  | }  | 
80  |  |  | 
81  |  | static PyObject *  | 
82  |  | iter_len(seqiterobject *it, PyObject *Py_UNUSED(ignored))  | 
83  | 2  | { | 
84  | 2  |     Py_ssize_t seqsize, len;  | 
85  |  |  | 
86  | 2  |     if (it->it_seq) { | 
87  | 2  |         if (_PyObject_HasLen(it->it_seq)) { | 
88  | 2  |             seqsize = PySequence_Size(it->it_seq);  | 
89  | 2  |             if (seqsize == -1)  | 
90  | 0  |                 return NULL;  | 
91  | 2  |         }  | 
92  | 0  |         else { | 
93  | 0  |             Py_RETURN_NOTIMPLEMENTED;  | 
94  | 0  |         }  | 
95  | 2  |         len = seqsize - it->it_index;  | 
96  | 2  |         if (len >= 0)  | 
97  | 2  |             return PyLong_FromSsize_t(len);  | 
98  | 2  |     }  | 
99  | 0  |     return PyLong_FromLong(0);  | 
100  | 2  | }  | 
101  |  |  | 
102  |  | PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");  | 
103  |  |  | 
104  |  | static PyObject *  | 
105  |  | iter_reduce(seqiterobject *it, PyObject *Py_UNUSED(ignored))  | 
106  | 0  | { | 
107  | 0  |     _Py_IDENTIFIER(iter);  | 
108  | 0  |     if (it->it_seq != NULL)  | 
109  | 0  |         return Py_BuildValue("N(O)n", _PyEval_GetBuiltinId(&PyId_iter), | 
110  | 0  |                              it->it_seq, it->it_index);  | 
111  | 0  |     else  | 
112  | 0  |         return Py_BuildValue("N(())", _PyEval_GetBuiltinId(&PyId_iter)); | 
113  | 0  | }  | 
114  |  |  | 
115  |  | PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");  | 
116  |  |  | 
117  |  | static PyObject *  | 
118  |  | iter_setstate(seqiterobject *it, PyObject *state)  | 
119  | 0  | { | 
120  | 0  |     Py_ssize_t index = PyLong_AsSsize_t(state);  | 
121  | 0  |     if (index == -1 && PyErr_Occurred())  | 
122  | 0  |         return NULL;  | 
123  | 0  |     if (it->it_seq != NULL) { | 
124  | 0  |         if (index < 0)  | 
125  | 0  |             index = 0;  | 
126  | 0  |         it->it_index = index;  | 
127  | 0  |     }  | 
128  | 0  |     Py_RETURN_NONE;  | 
129  | 0  | }  | 
130  |  |  | 
131  |  | PyDoc_STRVAR(setstate_doc, "Set state information for unpickling.");  | 
132  |  |  | 
133  |  | static PyMethodDef seqiter_methods[] = { | 
134  |  |     {"__length_hint__", (PyCFunction)iter_len, METH_NOARGS, length_hint_doc}, | 
135  |  |     {"__reduce__", (PyCFunction)iter_reduce, METH_NOARGS, reduce_doc}, | 
136  |  |     {"__setstate__", (PyCFunction)iter_setstate, METH_O, setstate_doc}, | 
137  |  |     {NULL,              NULL}           /* sentinel */ | 
138  |  | };  | 
139  |  |  | 
140  |  | PyTypeObject PySeqIter_Type = { | 
141  |  |     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 */  | 
147  |  |     0,                                          /* tp_vectorcall_offset */  | 
148  |  |     0,                                          /* tp_getattr */  | 
149  |  |     0,                                          /* tp_setattr */  | 
150  |  |     0,                                          /* tp_as_async */  | 
151  |  |     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 */  | 
171  |  | };  | 
172  |  |  | 
173  |  | /* -------------------------------------- */  | 
174  |  |  | 
175  |  | typedef struct { | 
176  |  |     PyObject_HEAD  | 
177  |  |     PyObject *it_callable; /* Set to NULL when iterator is exhausted */  | 
178  |  |     PyObject *it_sentinel; /* Set to NULL when iterator is exhausted */  | 
179  |  | } calliterobject;  | 
180  |  |  | 
181  |  | PyObject *  | 
182  |  | PyCallIter_New(PyObject *callable, PyObject *sentinel)  | 
183  | 0  | { | 
184  | 0  |     calliterobject *it;  | 
185  | 0  |     it = PyObject_GC_New(calliterobject, &PyCallIter_Type);  | 
186  | 0  |     if (it == NULL)  | 
187  | 0  |         return NULL;  | 
188  | 0  |     Py_INCREF(callable);  | 
189  | 0  |     it->it_callable = callable;  | 
190  | 0  |     Py_INCREF(sentinel);  | 
191  | 0  |     it->it_sentinel = sentinel;  | 
192  | 0  |     _PyObject_GC_TRACK(it);  | 
193  | 0  |     return (PyObject *)it;  | 
194  | 0  | }  | 
195  |  | static void  | 
196  |  | calliter_dealloc(calliterobject *it)  | 
197  | 0  | { | 
198  | 0  |     _PyObject_GC_UNTRACK(it);  | 
199  | 0  |     Py_XDECREF(it->it_callable);  | 
200  | 0  |     Py_XDECREF(it->it_sentinel);  | 
201  | 0  |     PyObject_GC_Del(it);  | 
202  | 0  | }  | 
203  |  |  | 
204  |  | static int  | 
205  |  | calliter_traverse(calliterobject *it, visitproc visit, void *arg)  | 
206  | 0  | { | 
207  | 0  |     Py_VISIT(it->it_callable);  | 
208  | 0  |     Py_VISIT(it->it_sentinel);  | 
209  | 0  |     return 0;  | 
210  | 0  | }  | 
211  |  |  | 
212  |  | static PyObject *  | 
213  |  | calliter_iternext(calliterobject *it)  | 
214  | 0  | { | 
215  | 0  |     PyObject *result;  | 
216  |  | 
  | 
217  | 0  |     if (it->it_callable == NULL) { | 
218  | 0  |         return NULL;  | 
219  | 0  |     }  | 
220  |  |  | 
221  | 0  |     result = _PyObject_CallNoArg(it->it_callable);  | 
222  | 0  |     if (result != NULL) { | 
223  | 0  |         int ok;  | 
224  |  | 
  | 
225  | 0  |         ok = PyObject_RichCompareBool(it->it_sentinel, result, Py_EQ);  | 
226  | 0  |         if (ok == 0) { | 
227  | 0  |             return result; /* Common case, fast path */  | 
228  | 0  |         }  | 
229  |  |  | 
230  | 0  |         Py_DECREF(result);  | 
231  | 0  |         if (ok > 0) { | 
232  | 0  |             Py_CLEAR(it->it_callable);  | 
233  | 0  |             Py_CLEAR(it->it_sentinel);  | 
234  | 0  |         }  | 
235  | 0  |     }  | 
236  | 0  |     else if (PyErr_ExceptionMatches(PyExc_StopIteration)) { | 
237  | 0  |         PyErr_Clear();  | 
238  | 0  |         Py_CLEAR(it->it_callable);  | 
239  | 0  |         Py_CLEAR(it->it_sentinel);  | 
240  | 0  |     }  | 
241  | 0  |     return NULL;  | 
242  | 0  | }  | 
243  |  |  | 
244  |  | static PyObject *  | 
245  |  | calliter_reduce(calliterobject *it, PyObject *Py_UNUSED(ignored))  | 
246  | 0  | { | 
247  | 0  |     _Py_IDENTIFIER(iter);  | 
248  | 0  |     if (it->it_callable != NULL && it->it_sentinel != NULL)  | 
249  | 0  |         return Py_BuildValue("N(OO)", _PyEval_GetBuiltinId(&PyId_iter), | 
250  | 0  |                              it->it_callable, it->it_sentinel);  | 
251  | 0  |     else  | 
252  | 0  |         return Py_BuildValue("N(())", _PyEval_GetBuiltinId(&PyId_iter)); | 
253  | 0  | }  | 
254  |  |  | 
255  |  | static PyMethodDef calliter_methods[] = { | 
256  |  |     {"__reduce__", (PyCFunction)calliter_reduce, METH_NOARGS, reduce_doc}, | 
257  |  |     {NULL,              NULL}           /* sentinel */ | 
258  |  | };  | 
259  |  |  | 
260  |  | PyTypeObject PyCallIter_Type = { | 
261  |  |     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 */  | 
267  |  |     0,                                          /* tp_vectorcall_offset */  | 
268  |  |     0,                                          /* tp_getattr */  | 
269  |  |     0,                                          /* tp_setattr */  | 
270  |  |     0,                                          /* tp_as_async */  | 
271  |  |     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 */  | 
289  |  |     calliter_methods,                           /* tp_methods */  | 
290  |  | };  | 
291  |  |  | 
292  |  |  |