Line data Source code
1 : /* Iterator objects */
2 :
3 : #include "Python.h"
4 :
5 : typedef struct {
6 : PyObject_HEAD
7 : long it_index;
8 : PyObject *it_seq; /* Set to NULL when iterator is exhausted */
9 : } seqiterobject;
10 :
11 : PyObject *
12 586 : PySeqIter_New(PyObject *seq)
13 : {
14 : seqiterobject *it;
15 :
16 586 : if (!PySequence_Check(seq)) {
17 0 : PyErr_BadInternalCall();
18 0 : return NULL;
19 : }
20 586 : it = PyObject_GC_New(seqiterobject, &PySeqIter_Type);
21 586 : if (it == NULL)
22 0 : return NULL;
23 586 : it->it_index = 0;
24 586 : Py_INCREF(seq);
25 586 : it->it_seq = seq;
26 586 : _PyObject_GC_TRACK(it);
27 586 : return (PyObject *)it;
28 : }
29 :
30 : static void
31 586 : iter_dealloc(seqiterobject *it)
32 : {
33 586 : _PyObject_GC_UNTRACK(it);
34 586 : Py_XDECREF(it->it_seq);
35 586 : PyObject_GC_Del(it);
36 586 : }
37 :
38 : static int
39 0 : iter_traverse(seqiterobject *it, visitproc visit, void *arg)
40 : {
41 0 : Py_VISIT(it->it_seq);
42 0 : return 0;
43 : }
44 :
45 : static PyObject *
46 1568 : iter_iternext(PyObject *iterator)
47 : {
48 : seqiterobject *it;
49 : PyObject *seq;
50 : PyObject *result;
51 :
52 : assert(PySeqIter_Check(iterator));
53 1568 : it = (seqiterobject *)iterator;
54 1568 : seq = it->it_seq;
55 1568 : if (seq == NULL)
56 0 : return NULL;
57 :
58 1568 : result = PySequence_GetItem(seq, it->it_index);
59 1568 : if (result != NULL) {
60 982 : it->it_index++;
61 982 : return result;
62 : }
63 586 : if (PyErr_ExceptionMatches(PyExc_IndexError) ||
64 0 : PyErr_ExceptionMatches(PyExc_StopIteration))
65 : {
66 586 : PyErr_Clear();
67 586 : Py_DECREF(seq);
68 586 : it->it_seq = NULL;
69 : }
70 586 : return NULL;
71 : }
72 :
73 : static PyObject *
74 0 : iter_len(seqiterobject *it)
75 : {
76 : Py_ssize_t seqsize, len;
77 :
78 0 : if (it->it_seq) {
79 0 : seqsize = PySequence_Size(it->it_seq);
80 0 : if (seqsize == -1)
81 0 : return NULL;
82 0 : len = seqsize - it->it_index;
83 0 : if (len >= 0)
84 0 : return PyLong_FromSsize_t(len);
85 : }
86 0 : return PyLong_FromLong(0);
87 : }
88 :
89 : PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
90 :
91 : static PyObject *
92 0 : iter_reduce(seqiterobject *it)
93 : {
94 0 : if (it->it_seq != NULL)
95 0 : return Py_BuildValue("N(O)n", _PyObject_GetBuiltin("iter"),
96 : it->it_seq, it->it_index);
97 : else
98 0 : return Py_BuildValue("N(())", _PyObject_GetBuiltin("iter"));
99 : }
100 :
101 : PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
102 :
103 : static PyObject *
104 0 : iter_setstate(seqiterobject *it, PyObject *state)
105 : {
106 0 : Py_ssize_t index = PyLong_AsSsize_t(state);
107 0 : if (index == -1 && PyErr_Occurred())
108 0 : return NULL;
109 0 : if (it->it_seq != NULL) {
110 0 : if (index < 0)
111 0 : index = 0;
112 0 : it->it_index = index;
113 : }
114 0 : Py_RETURN_NONE;
115 : }
116 :
117 : PyDoc_STRVAR(setstate_doc, "Set state information for unpickling.");
118 :
119 : static PyMethodDef seqiter_methods[] = {
120 : {"__length_hint__", (PyCFunction)iter_len, METH_NOARGS, length_hint_doc},
121 : {"__reduce__", (PyCFunction)iter_reduce, METH_NOARGS, reduce_doc},
122 : {"__setstate__", (PyCFunction)iter_setstate, METH_O, setstate_doc},
123 : {NULL, NULL} /* sentinel */
124 : };
125 :
126 : PyTypeObject PySeqIter_Type = {
127 : PyVarObject_HEAD_INIT(&PyType_Type, 0)
128 : "iterator", /* tp_name */
129 : sizeof(seqiterobject), /* tp_basicsize */
130 : 0, /* tp_itemsize */
131 : /* methods */
132 : (destructor)iter_dealloc, /* tp_dealloc */
133 : 0, /* tp_print */
134 : 0, /* tp_getattr */
135 : 0, /* tp_setattr */
136 : 0, /* tp_reserved */
137 : 0, /* tp_repr */
138 : 0, /* tp_as_number */
139 : 0, /* tp_as_sequence */
140 : 0, /* tp_as_mapping */
141 : 0, /* tp_hash */
142 : 0, /* tp_call */
143 : 0, /* tp_str */
144 : PyObject_GenericGetAttr, /* tp_getattro */
145 : 0, /* tp_setattro */
146 : 0, /* tp_as_buffer */
147 : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
148 : 0, /* tp_doc */
149 : (traverseproc)iter_traverse, /* tp_traverse */
150 : 0, /* tp_clear */
151 : 0, /* tp_richcompare */
152 : 0, /* tp_weaklistoffset */
153 : PyObject_SelfIter, /* tp_iter */
154 : iter_iternext, /* tp_iternext */
155 : seqiter_methods, /* tp_methods */
156 : 0, /* tp_members */
157 : };
158 :
159 : /* -------------------------------------- */
160 :
161 : typedef struct {
162 : PyObject_HEAD
163 : PyObject *it_callable; /* Set to NULL when iterator is exhausted */
164 : PyObject *it_sentinel; /* Set to NULL when iterator is exhausted */
165 : } calliterobject;
166 :
167 : PyObject *
168 1890 : PyCallIter_New(PyObject *callable, PyObject *sentinel)
169 : {
170 : calliterobject *it;
171 1890 : it = PyObject_GC_New(calliterobject, &PyCallIter_Type);
172 1890 : if (it == NULL)
173 0 : return NULL;
174 1890 : Py_INCREF(callable);
175 1890 : it->it_callable = callable;
176 1890 : Py_INCREF(sentinel);
177 1890 : it->it_sentinel = sentinel;
178 1890 : _PyObject_GC_TRACK(it);
179 1890 : return (PyObject *)it;
180 : }
181 : static void
182 1890 : calliter_dealloc(calliterobject *it)
183 : {
184 1890 : _PyObject_GC_UNTRACK(it);
185 1890 : Py_XDECREF(it->it_callable);
186 1890 : Py_XDECREF(it->it_sentinel);
187 1890 : PyObject_GC_Del(it);
188 1890 : }
189 :
190 : static int
191 0 : calliter_traverse(calliterobject *it, visitproc visit, void *arg)
192 : {
193 0 : Py_VISIT(it->it_callable);
194 0 : Py_VISIT(it->it_sentinel);
195 0 : return 0;
196 : }
197 :
198 : static PyObject *
199 1890 : calliter_iternext(calliterobject *it)
200 : {
201 1890 : if (it->it_callable != NULL) {
202 1890 : PyObject *args = PyTuple_New(0);
203 : PyObject *result;
204 1890 : if (args == NULL)
205 0 : return NULL;
206 1890 : result = PyObject_Call(it->it_callable, args, NULL);
207 1890 : Py_DECREF(args);
208 1890 : if (result != NULL) {
209 : int ok;
210 1890 : ok = PyObject_RichCompareBool(it->it_sentinel, result, Py_EQ);
211 1890 : if (ok == 0)
212 0 : return result; /* Common case, fast path */
213 1890 : Py_DECREF(result);
214 1890 : if (ok > 0) {
215 1890 : Py_CLEAR(it->it_callable);
216 1890 : Py_CLEAR(it->it_sentinel);
217 : }
218 : }
219 0 : else if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
220 0 : PyErr_Clear();
221 0 : Py_CLEAR(it->it_callable);
222 0 : Py_CLEAR(it->it_sentinel);
223 : }
224 : }
225 1890 : return NULL;
226 : }
227 :
228 : static PyObject *
229 0 : calliter_reduce(calliterobject *it)
230 : {
231 0 : if (it->it_callable != NULL && it->it_sentinel != NULL)
232 0 : return Py_BuildValue("N(OO)", _PyObject_GetBuiltin("iter"),
233 : it->it_callable, it->it_sentinel);
234 : else
235 0 : return Py_BuildValue("N(())", _PyObject_GetBuiltin("iter"));
236 : }
237 :
238 : static PyMethodDef calliter_methods[] = {
239 : {"__reduce__", (PyCFunction)calliter_reduce, METH_NOARGS, reduce_doc},
240 : {NULL, NULL} /* sentinel */
241 : };
242 :
243 : PyTypeObject PyCallIter_Type = {
244 : PyVarObject_HEAD_INIT(&PyType_Type, 0)
245 : "callable_iterator", /* tp_name */
246 : sizeof(calliterobject), /* tp_basicsize */
247 : 0, /* tp_itemsize */
248 : /* methods */
249 : (destructor)calliter_dealloc, /* tp_dealloc */
250 : 0, /* tp_print */
251 : 0, /* tp_getattr */
252 : 0, /* tp_setattr */
253 : 0, /* tp_reserved */
254 : 0, /* tp_repr */
255 : 0, /* tp_as_number */
256 : 0, /* tp_as_sequence */
257 : 0, /* tp_as_mapping */
258 : 0, /* tp_hash */
259 : 0, /* tp_call */
260 : 0, /* tp_str */
261 : PyObject_GenericGetAttr, /* tp_getattro */
262 : 0, /* tp_setattro */
263 : 0, /* tp_as_buffer */
264 : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
265 : 0, /* tp_doc */
266 : (traverseproc)calliter_traverse, /* tp_traverse */
267 : 0, /* tp_clear */
268 : 0, /* tp_richcompare */
269 : 0, /* tp_weaklistoffset */
270 : PyObject_SelfIter, /* tp_iter */
271 : (iternextfunc)calliter_iternext, /* tp_iternext */
272 : calliter_methods, /* tp_methods */
273 : };
274 :
275 :
|