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 3455 : PySeqIter_New(PyObject *seq)
13 : {
14 : seqiterobject *it;
15 :
16 3455 : if (!PySequence_Check(seq)) {
17 0 : PyErr_BadInternalCall();
18 0 : return NULL;
19 : }
20 3455 : it = PyObject_GC_New(seqiterobject, &PySeqIter_Type);
21 3455 : if (it == NULL)
22 0 : return NULL;
23 3455 : it->it_index = 0;
24 3455 : Py_INCREF(seq);
25 3455 : it->it_seq = seq;
26 3455 : _PyObject_GC_TRACK(it);
27 3455 : return (PyObject *)it;
28 : }
29 :
30 : static void
31 3455 : iter_dealloc(seqiterobject *it)
32 : {
33 3455 : _PyObject_GC_UNTRACK(it);
34 3455 : Py_XDECREF(it->it_seq);
35 3455 : PyObject_GC_Del(it);
36 3455 : }
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 11981 : iter_iternext(PyObject *iterator)
47 : {
48 : seqiterobject *it;
49 : PyObject *seq;
50 : PyObject *result;
51 :
52 : assert(PySeqIter_Check(iterator));
53 11981 : it = (seqiterobject *)iterator;
54 11981 : seq = it->it_seq;
55 11981 : if (seq == NULL)
56 0 : return NULL;
57 11981 : if (it->it_index == LONG_MAX) {
58 0 : PyErr_SetString(PyExc_OverflowError,
59 : "iter index too large");
60 0 : return NULL;
61 : }
62 :
63 11981 : result = PySequence_GetItem(seq, it->it_index);
64 11981 : if (result != NULL) {
65 8526 : it->it_index++;
66 8526 : return result;
67 : }
68 3455 : if (PyErr_ExceptionMatches(PyExc_IndexError) ||
69 0 : PyErr_ExceptionMatches(PyExc_StopIteration))
70 : {
71 3455 : PyErr_Clear();
72 3455 : it->it_seq = NULL;
73 3455 : Py_DECREF(seq);
74 : }
75 3455 : return NULL;
76 : }
77 :
78 : static PyObject *
79 0 : iter_len(seqiterobject *it)
80 : {
81 : Py_ssize_t seqsize, len;
82 :
83 0 : if (it->it_seq) {
84 0 : seqsize = PySequence_Size(it->it_seq);
85 0 : if (seqsize == -1)
86 0 : return NULL;
87 0 : len = seqsize - it->it_index;
88 0 : if (len >= 0)
89 0 : return PyInt_FromSsize_t(len);
90 : }
91 0 : return PyInt_FromLong(0);
92 : }
93 :
94 : PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
95 :
96 : static PyMethodDef seqiter_methods[] = {
97 : {"__length_hint__", (PyCFunction)iter_len, METH_NOARGS, length_hint_doc},
98 : {NULL, NULL} /* sentinel */
99 : };
100 :
101 : PyTypeObject PySeqIter_Type = {
102 : PyVarObject_HEAD_INIT(&PyType_Type, 0)
103 : "iterator", /* tp_name */
104 : sizeof(seqiterobject), /* tp_basicsize */
105 : 0, /* tp_itemsize */
106 : /* methods */
107 : (destructor)iter_dealloc, /* tp_dealloc */
108 : 0, /* tp_print */
109 : 0, /* tp_getattr */
110 : 0, /* tp_setattr */
111 : 0, /* tp_compare */
112 : 0, /* tp_repr */
113 : 0, /* tp_as_number */
114 : 0, /* tp_as_sequence */
115 : 0, /* tp_as_mapping */
116 : 0, /* tp_hash */
117 : 0, /* tp_call */
118 : 0, /* tp_str */
119 : PyObject_GenericGetAttr, /* tp_getattro */
120 : 0, /* tp_setattro */
121 : 0, /* tp_as_buffer */
122 : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
123 : 0, /* tp_doc */
124 : (traverseproc)iter_traverse, /* tp_traverse */
125 : 0, /* tp_clear */
126 : 0, /* tp_richcompare */
127 : 0, /* tp_weaklistoffset */
128 : PyObject_SelfIter, /* tp_iter */
129 : iter_iternext, /* tp_iternext */
130 : seqiter_methods, /* tp_methods */
131 : 0, /* tp_members */
132 : };
133 :
134 : /* -------------------------------------- */
135 :
136 : typedef struct {
137 : PyObject_HEAD
138 : PyObject *it_callable; /* Set to NULL when iterator is exhausted */
139 : PyObject *it_sentinel; /* Set to NULL when iterator is exhausted */
140 : } calliterobject;
141 :
142 : PyObject *
143 753 : PyCallIter_New(PyObject *callable, PyObject *sentinel)
144 : {
145 : calliterobject *it;
146 753 : it = PyObject_GC_New(calliterobject, &PyCallIter_Type);
147 753 : if (it == NULL)
148 0 : return NULL;
149 753 : Py_INCREF(callable);
150 753 : it->it_callable = callable;
151 753 : Py_INCREF(sentinel);
152 753 : it->it_sentinel = sentinel;
153 753 : _PyObject_GC_TRACK(it);
154 753 : return (PyObject *)it;
155 : }
156 : static void
157 753 : calliter_dealloc(calliterobject *it)
158 : {
159 753 : _PyObject_GC_UNTRACK(it);
160 753 : Py_XDECREF(it->it_callable);
161 753 : Py_XDECREF(it->it_sentinel);
162 753 : PyObject_GC_Del(it);
163 753 : }
164 :
165 : static int
166 6 : calliter_traverse(calliterobject *it, visitproc visit, void *arg)
167 : {
168 6 : Py_VISIT(it->it_callable);
169 6 : Py_VISIT(it->it_sentinel);
170 6 : return 0;
171 : }
172 :
173 : static PyObject *
174 3165 : calliter_iternext(calliterobject *it)
175 : {
176 3165 : if (it->it_callable != NULL) {
177 3165 : PyObject *args = PyTuple_New(0);
178 : PyObject *result;
179 3165 : if (args == NULL)
180 0 : return NULL;
181 3165 : result = PyObject_Call(it->it_callable, args, NULL);
182 3165 : Py_DECREF(args);
183 3165 : if (result != NULL) {
184 : int ok;
185 3165 : ok = PyObject_RichCompareBool(result,
186 : it->it_sentinel,
187 : Py_EQ);
188 3165 : if (ok == 0)
189 2760 : return result; /* Common case, fast path */
190 405 : Py_DECREF(result);
191 405 : if (ok > 0) {
192 405 : Py_CLEAR(it->it_callable);
193 405 : Py_CLEAR(it->it_sentinel);
194 : }
195 : }
196 0 : else if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
197 0 : PyErr_Clear();
198 0 : Py_CLEAR(it->it_callable);
199 0 : Py_CLEAR(it->it_sentinel);
200 : }
201 : }
202 405 : return NULL;
203 : }
204 :
205 : PyTypeObject PyCallIter_Type = {
206 : PyVarObject_HEAD_INIT(&PyType_Type, 0)
207 : "callable-iterator", /* tp_name */
208 : sizeof(calliterobject), /* tp_basicsize */
209 : 0, /* tp_itemsize */
210 : /* methods */
211 : (destructor)calliter_dealloc, /* tp_dealloc */
212 : 0, /* tp_print */
213 : 0, /* tp_getattr */
214 : 0, /* tp_setattr */
215 : 0, /* tp_compare */
216 : 0, /* tp_repr */
217 : 0, /* tp_as_number */
218 : 0, /* tp_as_sequence */
219 : 0, /* tp_as_mapping */
220 : 0, /* tp_hash */
221 : 0, /* tp_call */
222 : 0, /* tp_str */
223 : PyObject_GenericGetAttr, /* tp_getattro */
224 : 0, /* tp_setattro */
225 : 0, /* tp_as_buffer */
226 : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
227 : 0, /* tp_doc */
228 : (traverseproc)calliter_traverse, /* tp_traverse */
229 : 0, /* tp_clear */
230 : 0, /* tp_richcompare */
231 : 0, /* tp_weaklistoffset */
232 : PyObject_SelfIter, /* tp_iter */
233 : (iternextfunc)calliter_iternext, /* tp_iternext */
234 : 0, /* tp_methods */
235 : };
|