blob: 447edbac503d6e56cc6565b580936e53409bf1fb [file] [log] [blame]
Guido van Rossum05311482001-04-20 21:06:46 +00001/* Iterator objects */
2
3#include "Python.h"
4
5typedef struct {
6 PyObject_HEAD
7 long it_index;
Guido van Rossum613bed32002-07-16 20:24:46 +00008 PyObject *it_seq; /* Set to NULL when iterator is exhausted */
Guido van Rossum213c7a62001-04-23 14:08:49 +00009} seqiterobject;
Guido van Rossum05311482001-04-20 21:06:46 +000010
11PyObject *
Guido van Rossum213c7a62001-04-23 14:08:49 +000012PySeqIter_New(PyObject *seq)
Guido van Rossum05311482001-04-20 21:06:46 +000013{
Guido van Rossum213c7a62001-04-23 14:08:49 +000014 seqiterobject *it;
Martin v. Löwis01f94bd2002-05-08 08:44:21 +000015
16 if (!PySequence_Check(seq)) {
17 PyErr_BadInternalCall();
18 return NULL;
19 }
Neil Schemenauerdbf409f2002-03-18 20:43:51 +000020 it = PyObject_GC_New(seqiterobject, &PySeqIter_Type);
Guido van Rossum05311482001-04-20 21:06:46 +000021 if (it == NULL)
22 return NULL;
23 it->it_index = 0;
24 Py_INCREF(seq);
25 it->it_seq = seq;
Neil Schemenauerdbf409f2002-03-18 20:43:51 +000026 _PyObject_GC_TRACK(it);
Guido van Rossum05311482001-04-20 21:06:46 +000027 return (PyObject *)it;
28}
Guido van Rossum613bed32002-07-16 20:24:46 +000029
Guido van Rossum05311482001-04-20 21:06:46 +000030static void
Guido van Rossum213c7a62001-04-23 14:08:49 +000031iter_dealloc(seqiterobject *it)
Guido van Rossum05311482001-04-20 21:06:46 +000032{
Neil Schemenauerdbf409f2002-03-18 20:43:51 +000033 _PyObject_GC_UNTRACK(it);
Guido van Rossum613bed32002-07-16 20:24:46 +000034 Py_XDECREF(it->it_seq);
Neil Schemenauerdbf409f2002-03-18 20:43:51 +000035 PyObject_GC_Del(it);
Guido van Rossum05311482001-04-20 21:06:46 +000036}
37
Neil Schemenauer7eac9b72001-07-12 13:27:25 +000038static int
39iter_traverse(seqiterobject *it, visitproc visit, void *arg)
40{
Guido van Rossum613bed32002-07-16 20:24:46 +000041 if (it->it_seq == NULL)
42 return 0;
Neil Schemenauer7eac9b72001-07-12 13:27:25 +000043 return visit(it->it_seq, arg);
44}
45
Guido van Rossum05311482001-04-20 21:06:46 +000046static PyObject *
Guido van Rossum05311482001-04-20 21:06:46 +000047iter_getiter(PyObject *it)
48{
49 Py_INCREF(it);
50 return it;
51}
52
Guido van Rossum213c7a62001-04-23 14:08:49 +000053static PyObject *
54iter_iternext(PyObject *iterator)
55{
56 seqiterobject *it;
57 PyObject *seq;
58
59 assert(PySeqIter_Check(iterator));
60 it = (seqiterobject *)iterator;
61 seq = it->it_seq;
Guido van Rossum613bed32002-07-16 20:24:46 +000062 if (seq == NULL)
63 return NULL;
Guido van Rossum213c7a62001-04-23 14:08:49 +000064
Martin v. Löwis01f94bd2002-05-08 08:44:21 +000065 if (PyTuple_CheckExact(seq)) {
Raymond Hettinger14bd6de2002-05-31 21:40:38 +000066 if (it->it_index < PyTuple_GET_SIZE(seq)) {
67 PyObject *item;
68 item = PyTuple_GET_ITEM(seq, it->it_index);
69 it->it_index++;
70 Py_INCREF(item);
71 return item;
Martin v. Löwis01f94bd2002-05-08 08:44:21 +000072 }
Guido van Rossum613bed32002-07-16 20:24:46 +000073 Py_DECREF(seq);
74 it->it_seq = NULL;
Raymond Hettinger14bd6de2002-05-31 21:40:38 +000075 return NULL;
Martin v. Löwis01f94bd2002-05-08 08:44:21 +000076 }
Guido van Rossum213c7a62001-04-23 14:08:49 +000077 else {
Guido van Rossum613bed32002-07-16 20:24:46 +000078 PyObject *result = PySequence_GetItem(seq, it->it_index);
Guido van Rossum213c7a62001-04-23 14:08:49 +000079 if (result != NULL) {
Guido van Rossum613bed32002-07-16 20:24:46 +000080 it->it_index++;
Guido van Rossum213c7a62001-04-23 14:08:49 +000081 return result;
82 }
83 if (PyErr_ExceptionMatches(PyExc_IndexError) ||
Guido van Rossum613bed32002-07-16 20:24:46 +000084 PyErr_ExceptionMatches(PyExc_StopIteration))
85 {
Guido van Rossum213c7a62001-04-23 14:08:49 +000086 PyErr_Clear();
Guido van Rossum613bed32002-07-16 20:24:46 +000087 Py_DECREF(seq);
88 it->it_seq = NULL;
Guido van Rossum213c7a62001-04-23 14:08:49 +000089 }
Guido van Rossum613bed32002-07-16 20:24:46 +000090 return NULL;
Guido van Rossum213c7a62001-04-23 14:08:49 +000091 }
92}
93
Guido van Rossum213c7a62001-04-23 14:08:49 +000094PyTypeObject PySeqIter_Type = {
Guido van Rossum05311482001-04-20 21:06:46 +000095 PyObject_HEAD_INIT(&PyType_Type)
96 0, /* ob_size */
97 "iterator", /* tp_name */
Neil Schemenauerdbf409f2002-03-18 20:43:51 +000098 sizeof(seqiterobject), /* tp_basicsize */
Guido van Rossum05311482001-04-20 21:06:46 +000099 0, /* tp_itemsize */
100 /* methods */
101 (destructor)iter_dealloc, /* tp_dealloc */
102 0, /* tp_print */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000103 0, /* tp_getattr */
Guido van Rossum05311482001-04-20 21:06:46 +0000104 0, /* tp_setattr */
105 0, /* tp_compare */
106 0, /* tp_repr */
107 0, /* tp_as_number */
108 0, /* tp_as_sequence */
109 0, /* tp_as_mapping */
110 0, /* tp_hash */
111 0, /* tp_call */
112 0, /* tp_str */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000113 PyObject_GenericGetAttr, /* tp_getattro */
Guido van Rossum05311482001-04-20 21:06:46 +0000114 0, /* tp_setattro */
115 0, /* tp_as_buffer */
Neil Schemenauerdbf409f2002-03-18 20:43:51 +0000116 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
Guido van Rossum05311482001-04-20 21:06:46 +0000117 0, /* tp_doc */
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000118 (traverseproc)iter_traverse, /* tp_traverse */
Guido van Rossum05311482001-04-20 21:06:46 +0000119 0, /* tp_clear */
120 0, /* tp_richcompare */
121 0, /* tp_weaklistoffset */
122 (getiterfunc)iter_getiter, /* tp_iter */
Guido van Rossum213c7a62001-04-23 14:08:49 +0000123 (iternextfunc)iter_iternext, /* tp_iternext */
Guido van Rossum613bed32002-07-16 20:24:46 +0000124 0, /* tp_methods */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000125 0, /* tp_members */
126 0, /* tp_getset */
127 0, /* tp_base */
128 0, /* tp_dict */
129 0, /* tp_descr_get */
130 0, /* tp_descr_set */
Guido van Rossum05311482001-04-20 21:06:46 +0000131};
132
133/* -------------------------------------- */
134
135typedef struct {
136 PyObject_HEAD
Guido van Rossum613bed32002-07-16 20:24:46 +0000137 PyObject *it_callable; /* Set to NULL when iterator is exhausted */
138 PyObject *it_sentinel; /* Set to NULL when iterator is exhausted */
Guido van Rossum05311482001-04-20 21:06:46 +0000139} calliterobject;
140
141PyObject *
142PyCallIter_New(PyObject *callable, PyObject *sentinel)
143{
144 calliterobject *it;
Neil Schemenauerdbf409f2002-03-18 20:43:51 +0000145 it = PyObject_GC_New(calliterobject, &PyCallIter_Type);
Guido van Rossum05311482001-04-20 21:06:46 +0000146 if (it == NULL)
147 return NULL;
148 Py_INCREF(callable);
149 it->it_callable = callable;
150 Py_INCREF(sentinel);
151 it->it_sentinel = sentinel;
Neil Schemenauerdbf409f2002-03-18 20:43:51 +0000152 _PyObject_GC_TRACK(it);
Guido van Rossum05311482001-04-20 21:06:46 +0000153 return (PyObject *)it;
154}
155static void
156calliter_dealloc(calliterobject *it)
157{
Neil Schemenauerdbf409f2002-03-18 20:43:51 +0000158 _PyObject_GC_UNTRACK(it);
Guido van Rossum613bed32002-07-16 20:24:46 +0000159 Py_XDECREF(it->it_callable);
160 Py_XDECREF(it->it_sentinel);
Neil Schemenauerdbf409f2002-03-18 20:43:51 +0000161 PyObject_GC_Del(it);
Guido van Rossum05311482001-04-20 21:06:46 +0000162}
Guido van Rossum213c7a62001-04-23 14:08:49 +0000163
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000164static int
165calliter_traverse(calliterobject *it, visitproc visit, void *arg)
166{
167 int err;
Guido van Rossum613bed32002-07-16 20:24:46 +0000168 if (it->it_callable != NULL && (err = visit(it->it_callable, arg)))
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000169 return err;
Guido van Rossum613bed32002-07-16 20:24:46 +0000170 if (it->it_sentinel != NULL && (err = visit(it->it_sentinel, arg)))
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000171 return err;
172 return 0;
173}
174
Guido van Rossum05311482001-04-20 21:06:46 +0000175static PyObject *
Guido van Rossum213c7a62001-04-23 14:08:49 +0000176calliter_iternext(calliterobject *it)
177{
Guido van Rossum613bed32002-07-16 20:24:46 +0000178 if (it->it_callable != NULL) {
179 PyObject *result = PyObject_CallObject(it->it_callable, NULL);
180 if (result != NULL) {
181 int ok;
182 ok = PyObject_RichCompareBool(result,
183 it->it_sentinel,
184 Py_EQ);
185 if (ok == 0)
186 return result; /* Common case, fast path */
Guido van Rossum213c7a62001-04-23 14:08:49 +0000187 Py_DECREF(result);
Guido van Rossum613bed32002-07-16 20:24:46 +0000188 if (ok > 0) {
189 Py_DECREF(it->it_callable);
190 it->it_callable = NULL;
191 Py_DECREF(it->it_sentinel);
192 it->it_sentinel = NULL;
193 }
194 }
195 else if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
196 PyErr_Clear();
197 Py_DECREF(it->it_callable);
198 it->it_callable = NULL;
199 Py_DECREF(it->it_sentinel);
200 it->it_sentinel = NULL;
Guido van Rossum213c7a62001-04-23 14:08:49 +0000201 }
202 }
Guido van Rossum613bed32002-07-16 20:24:46 +0000203 return NULL;
Guido van Rossum213c7a62001-04-23 14:08:49 +0000204}
205
Guido van Rossum05311482001-04-20 21:06:46 +0000206PyTypeObject PyCallIter_Type = {
207 PyObject_HEAD_INIT(&PyType_Type)
208 0, /* ob_size */
209 "callable-iterator", /* tp_name */
Neil Schemenauerdbf409f2002-03-18 20:43:51 +0000210 sizeof(calliterobject), /* tp_basicsize */
Guido van Rossum05311482001-04-20 21:06:46 +0000211 0, /* tp_itemsize */
212 /* methods */
213 (destructor)calliter_dealloc, /* tp_dealloc */
214 0, /* tp_print */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000215 0, /* tp_getattr */
Guido van Rossum05311482001-04-20 21:06:46 +0000216 0, /* tp_setattr */
217 0, /* tp_compare */
218 0, /* tp_repr */
219 0, /* tp_as_number */
220 0, /* tp_as_sequence */
221 0, /* tp_as_mapping */
222 0, /* tp_hash */
223 0, /* tp_call */
224 0, /* tp_str */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000225 PyObject_GenericGetAttr, /* tp_getattro */
Guido van Rossum05311482001-04-20 21:06:46 +0000226 0, /* tp_setattro */
227 0, /* tp_as_buffer */
Neil Schemenauerdbf409f2002-03-18 20:43:51 +0000228 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
Guido van Rossum05311482001-04-20 21:06:46 +0000229 0, /* tp_doc */
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000230 (traverseproc)calliter_traverse, /* tp_traverse */
Guido van Rossum05311482001-04-20 21:06:46 +0000231 0, /* tp_clear */
232 0, /* tp_richcompare */
233 0, /* tp_weaklistoffset */
234 (getiterfunc)iter_getiter, /* tp_iter */
Guido van Rossum213c7a62001-04-23 14:08:49 +0000235 (iternextfunc)calliter_iternext, /* tp_iternext */
Guido van Rossum613bed32002-07-16 20:24:46 +0000236 0, /* tp_methods */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000237 0, /* tp_members */
238 0, /* tp_getset */
239 0, /* tp_base */
240 0, /* tp_dict */
241 0, /* tp_descr_get */
242 0, /* tp_descr_set */
Guido van Rossum05311482001-04-20 21:06:46 +0000243};