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