blob: 2e1caae543708a8978623ab4301c11c6a123daab [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;
Raymond Hettinger48923c52002-08-09 01:30:17 +000058 PyObject *result;
Guido van Rossum213c7a62001-04-23 14:08:49 +000059
60 assert(PySeqIter_Check(iterator));
61 it = (seqiterobject *)iterator;
62 seq = it->it_seq;
Guido van Rossum613bed32002-07-16 20:24:46 +000063 if (seq == NULL)
64 return NULL;
Guido van Rossum213c7a62001-04-23 14:08:49 +000065
Raymond Hettinger48923c52002-08-09 01:30:17 +000066 result = PySequence_GetItem(seq, it->it_index);
67 if (result != NULL) {
68 it->it_index++;
69 return result;
70 }
71 if (PyErr_ExceptionMatches(PyExc_IndexError) ||
72 PyErr_ExceptionMatches(PyExc_StopIteration))
73 {
74 PyErr_Clear();
Guido van Rossum613bed32002-07-16 20:24:46 +000075 Py_DECREF(seq);
76 it->it_seq = NULL;
Martin v. Löwis01f94bd2002-05-08 08:44:21 +000077 }
Raymond Hettinger48923c52002-08-09 01:30:17 +000078 return NULL;
Guido van Rossum213c7a62001-04-23 14:08:49 +000079}
80
Guido van Rossum213c7a62001-04-23 14:08:49 +000081PyTypeObject PySeqIter_Type = {
Guido van Rossum05311482001-04-20 21:06:46 +000082 PyObject_HEAD_INIT(&PyType_Type)
83 0, /* ob_size */
84 "iterator", /* tp_name */
Neil Schemenauerdbf409f2002-03-18 20:43:51 +000085 sizeof(seqiterobject), /* tp_basicsize */
Guido van Rossum05311482001-04-20 21:06:46 +000086 0, /* tp_itemsize */
87 /* methods */
88 (destructor)iter_dealloc, /* tp_dealloc */
89 0, /* tp_print */
Tim Peters6d6c1a32001-08-02 04:15:00 +000090 0, /* tp_getattr */
Guido van Rossum05311482001-04-20 21:06:46 +000091 0, /* tp_setattr */
92 0, /* tp_compare */
93 0, /* tp_repr */
94 0, /* tp_as_number */
95 0, /* tp_as_sequence */
96 0, /* tp_as_mapping */
97 0, /* tp_hash */
98 0, /* tp_call */
99 0, /* tp_str */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000100 PyObject_GenericGetAttr, /* tp_getattro */
Guido van Rossum05311482001-04-20 21:06:46 +0000101 0, /* tp_setattro */
102 0, /* tp_as_buffer */
Neil Schemenauerdbf409f2002-03-18 20:43:51 +0000103 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
Guido van Rossum05311482001-04-20 21:06:46 +0000104 0, /* tp_doc */
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000105 (traverseproc)iter_traverse, /* tp_traverse */
Guido van Rossum05311482001-04-20 21:06:46 +0000106 0, /* tp_clear */
107 0, /* tp_richcompare */
108 0, /* tp_weaklistoffset */
109 (getiterfunc)iter_getiter, /* tp_iter */
Guido van Rossum213c7a62001-04-23 14:08:49 +0000110 (iternextfunc)iter_iternext, /* tp_iternext */
Guido van Rossum613bed32002-07-16 20:24:46 +0000111 0, /* tp_methods */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000112 0, /* tp_members */
113 0, /* tp_getset */
114 0, /* tp_base */
115 0, /* tp_dict */
116 0, /* tp_descr_get */
117 0, /* tp_descr_set */
Guido van Rossum05311482001-04-20 21:06:46 +0000118};
119
120/* -------------------------------------- */
121
122typedef struct {
123 PyObject_HEAD
Guido van Rossum613bed32002-07-16 20:24:46 +0000124 PyObject *it_callable; /* Set to NULL when iterator is exhausted */
125 PyObject *it_sentinel; /* Set to NULL when iterator is exhausted */
Guido van Rossum05311482001-04-20 21:06:46 +0000126} calliterobject;
127
128PyObject *
129PyCallIter_New(PyObject *callable, PyObject *sentinel)
130{
131 calliterobject *it;
Neil Schemenauerdbf409f2002-03-18 20:43:51 +0000132 it = PyObject_GC_New(calliterobject, &PyCallIter_Type);
Guido van Rossum05311482001-04-20 21:06:46 +0000133 if (it == NULL)
134 return NULL;
135 Py_INCREF(callable);
136 it->it_callable = callable;
137 Py_INCREF(sentinel);
138 it->it_sentinel = sentinel;
Neil Schemenauerdbf409f2002-03-18 20:43:51 +0000139 _PyObject_GC_TRACK(it);
Guido van Rossum05311482001-04-20 21:06:46 +0000140 return (PyObject *)it;
141}
142static void
143calliter_dealloc(calliterobject *it)
144{
Neil Schemenauerdbf409f2002-03-18 20:43:51 +0000145 _PyObject_GC_UNTRACK(it);
Guido van Rossum613bed32002-07-16 20:24:46 +0000146 Py_XDECREF(it->it_callable);
147 Py_XDECREF(it->it_sentinel);
Neil Schemenauerdbf409f2002-03-18 20:43:51 +0000148 PyObject_GC_Del(it);
Guido van Rossum05311482001-04-20 21:06:46 +0000149}
Guido van Rossum213c7a62001-04-23 14:08:49 +0000150
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000151static int
152calliter_traverse(calliterobject *it, visitproc visit, void *arg)
153{
154 int err;
Guido van Rossum613bed32002-07-16 20:24:46 +0000155 if (it->it_callable != NULL && (err = visit(it->it_callable, arg)))
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000156 return err;
Guido van Rossum613bed32002-07-16 20:24:46 +0000157 if (it->it_sentinel != NULL && (err = visit(it->it_sentinel, arg)))
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000158 return err;
159 return 0;
160}
161
Guido van Rossum05311482001-04-20 21:06:46 +0000162static PyObject *
Guido van Rossum213c7a62001-04-23 14:08:49 +0000163calliter_iternext(calliterobject *it)
164{
Guido van Rossum613bed32002-07-16 20:24:46 +0000165 if (it->it_callable != NULL) {
Guido van Rossum84b2bed2002-08-16 17:01:09 +0000166 PyObject *args = PyTuple_New(0);
167 PyObject *result;
168 if (args == NULL)
169 return NULL;
170 result = PyObject_Call(it->it_callable, args, NULL);
171 Py_DECREF(args);
Guido van Rossum613bed32002-07-16 20:24:46 +0000172 if (result != NULL) {
173 int ok;
174 ok = PyObject_RichCompareBool(result,
175 it->it_sentinel,
176 Py_EQ);
177 if (ok == 0)
178 return result; /* Common case, fast path */
Guido van Rossum213c7a62001-04-23 14:08:49 +0000179 Py_DECREF(result);
Guido van Rossum613bed32002-07-16 20:24:46 +0000180 if (ok > 0) {
181 Py_DECREF(it->it_callable);
182 it->it_callable = NULL;
183 Py_DECREF(it->it_sentinel);
184 it->it_sentinel = NULL;
185 }
186 }
187 else if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
188 PyErr_Clear();
189 Py_DECREF(it->it_callable);
190 it->it_callable = NULL;
191 Py_DECREF(it->it_sentinel);
192 it->it_sentinel = NULL;
Guido van Rossum213c7a62001-04-23 14:08:49 +0000193 }
194 }
Guido van Rossum613bed32002-07-16 20:24:46 +0000195 return NULL;
Guido van Rossum213c7a62001-04-23 14:08:49 +0000196}
197
Guido van Rossum05311482001-04-20 21:06:46 +0000198PyTypeObject PyCallIter_Type = {
199 PyObject_HEAD_INIT(&PyType_Type)
200 0, /* ob_size */
201 "callable-iterator", /* tp_name */
Neil Schemenauerdbf409f2002-03-18 20:43:51 +0000202 sizeof(calliterobject), /* tp_basicsize */
Guido van Rossum05311482001-04-20 21:06:46 +0000203 0, /* tp_itemsize */
204 /* methods */
205 (destructor)calliter_dealloc, /* tp_dealloc */
206 0, /* tp_print */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000207 0, /* tp_getattr */
Guido van Rossum05311482001-04-20 21:06:46 +0000208 0, /* tp_setattr */
209 0, /* tp_compare */
210 0, /* tp_repr */
211 0, /* tp_as_number */
212 0, /* tp_as_sequence */
213 0, /* tp_as_mapping */
214 0, /* tp_hash */
215 0, /* tp_call */
216 0, /* tp_str */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000217 PyObject_GenericGetAttr, /* tp_getattro */
Guido van Rossum05311482001-04-20 21:06:46 +0000218 0, /* tp_setattro */
219 0, /* tp_as_buffer */
Neil Schemenauerdbf409f2002-03-18 20:43:51 +0000220 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
Guido van Rossum05311482001-04-20 21:06:46 +0000221 0, /* tp_doc */
Neil Schemenauer7eac9b72001-07-12 13:27:25 +0000222 (traverseproc)calliter_traverse, /* tp_traverse */
Guido van Rossum05311482001-04-20 21:06:46 +0000223 0, /* tp_clear */
224 0, /* tp_richcompare */
225 0, /* tp_weaklistoffset */
226 (getiterfunc)iter_getiter, /* tp_iter */
Guido van Rossum213c7a62001-04-23 14:08:49 +0000227 (iternextfunc)calliter_iternext, /* tp_iternext */
Guido van Rossum613bed32002-07-16 20:24:46 +0000228 0, /* tp_methods */
Tim Peters6d6c1a32001-08-02 04:15:00 +0000229 0, /* tp_members */
230 0, /* tp_getset */
231 0, /* tp_base */
232 0, /* tp_dict */
233 0, /* tp_descr_get */
234 0, /* tp_descr_set */
Guido van Rossum05311482001-04-20 21:06:46 +0000235};